home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / djgpp / src / gas-211 / gas / config / tc-hppa.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-30  |  142.0 KB  |  5,548 lines

  1. /* tc-hppa.c -- Assemble for the PA
  2.    Copyright (C) 1989 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  21. /*
  22.    HP PA-RISC support was contributed by the Center for Software Science
  23.    at the University of Utah.
  24.  */
  25.  
  26. #include <stdio.h>
  27. #include <ctype.h>
  28.  
  29. #include "as.h"
  30. #include "subsegs.h"
  31.  
  32. /* #include "../bfd/libhppa.h" */
  33. /*
  34.  * Unwind table and descriptor.
  35.  */
  36.  
  37. struct unwind_desc {
  38.   unsigned int cannot_unwind         :  1;
  39.   unsigned int millicode             :  1;
  40.   unsigned int millicode_save_rest   :  1;
  41.   unsigned int region_desc           :  2;
  42.   unsigned int save_sr               :  2;
  43.   unsigned int entry_fr              :  4;        /* number saved */
  44.   unsigned int entry_gr              :  5;        /* number saved */
  45.   unsigned int args_stored           :  1;
  46.   unsigned int call_fr               :  5;
  47.   unsigned int call_gr               :  5;
  48.   unsigned int save_sp               :  1;
  49.   unsigned int save_rp               :  1;
  50.   unsigned int save_rp_in_frame      :  1;
  51.   unsigned int extn_ptr_defined      :  1;
  52.   unsigned int cleanup_defined       :  1;
  53.  
  54.   unsigned int hpe_interrupt_marker  :  1;
  55.   unsigned int hpux_interrupt_marker :  1;
  56.   unsigned int reserved              :  3;
  57.   unsigned int frame_size            : 27;
  58. };
  59.  
  60. typedef struct unwind_desc unwind_descS;
  61.  
  62. struct unwind_table {
  63.   unsigned int start_offset;  /* starting offset (from SR4) of applicable region */
  64.   unsigned int end_offset;    /* ending offset (from SR4) of applicable region */
  65.   unwind_descS descriptor;
  66. };
  67.  
  68. typedef struct unwind_table unwind_tableS;
  69.  
  70. /*
  71.  * This structure is used by the .callinfo, .enter, .leave pseudo-ops to
  72.  * control the entry and exit code they generate. It is also used in
  73.  * creation of the correct stack unwind descriptors.
  74.  *
  75.  * The fields in structure roughly correspond to the arguments available on the
  76.  * .callinfo pseudo-op.
  77.  */
  78.  
  79. struct call_info {
  80.   int frame;
  81.   int entry_sr;
  82.   int makes_calls;
  83.   int hpux_int;
  84.   unwind_tableS ci_unwind;    /* the unwind descriptor we are building */
  85.   symbolS *start_symbol;    /* name of function (used in relocation info) */
  86.   symbolS *end_symbol;        /* temporary symbol used to mark the */
  87.                 /* end of the function (used in */
  88.                 /* relocation info) */
  89.   fragS *start_frag;        /* frag associated w/ start of this function */
  90.   fragS *end_frag;        /* frag associated w/ end of this function */
  91.   fragS *start_offset_frag;    /* frag for start offset of this descriptor */
  92.   int   start_frag_where;    /* where in start_offset_frag is start_offset */
  93.   fixS *start_fix;        /* fixup for the start_offset */
  94.   fragS *end_offset_frag;    /* frag for start offset of this descriptor */
  95.   int   end_frag_where;        /* where in end_offset_frag is end_offset */
  96.   fixS *end_fix;        /* fixup for the end_offset */
  97.   struct call_info *ci_next;    /* the next call_info structure */
  98. };
  99.  
  100. typedef struct call_info call_infoS;
  101.  
  102. call_infoS *last_call_info;
  103. call_infoS *call_info_root;
  104. call_descS last_call_desc;
  105.  
  106. /* A structure used during assembly of individual instructions */
  107.  
  108. struct pa_it {
  109.     char    *error;
  110.     unsigned long opcode;
  111.     /* symbol_dictS *nlistp; *//*** used to be:    struct nlist *nlistp; */
  112.     asymbol * nlistp;
  113.     expressionS exp;
  114.     int pcrel;
  115.     FP_Operand_Format fpof1;   /* Floating Point Operand Format, operand 1 */
  116.     FP_Operand_Format fpof2;   /* Floating Point Operand Format, operand 2 */
  117.                                /* (used only for class 1 instructions --   */
  118.                    /* the conversion instructions)             */
  119. #ifdef OBJ_SOM
  120.     long field_selector;
  121.     unsigned int reloc;
  122.     int code;
  123.     long arg_reloc;
  124.     unwind_descS unwind;
  125. #endif
  126. #ifdef OBJ_ELF
  127.     elf32_hppa_reloc_type reloc;
  128.     long field_selector;
  129.     int format;
  130.     long arg_reloc;
  131.     unwind_descS unwind;
  132. #endif
  133. };
  134.  
  135. extern struct pa_it the_insn;
  136.  
  137. /* careful, this file includes data *declarations* */
  138. #include "opcode/hppa.h"
  139.  
  140. void md_begin();
  141. void md_end();
  142. void md_number_to_chars();
  143. void md_assemble();
  144. char *md_atof();
  145. void md_convert_frag();
  146. void md_create_short_jump();
  147. void md_create_long_jump();
  148. int  md_estimate_size_before_relax();
  149. void md_number_to_imm();
  150. void md_number_to_disp();
  151. void md_number_to_field();
  152. void md_ri_to_chars();
  153. void emit_relocations();
  154. static void pa_ip();
  155.  
  156.  
  157. /* SKV 10/18/92.  Added the following to assist in the determination of the
  158.    relocation to be applied to an instruction. */
  159.  
  160. #ifdef OBJ_ELF
  161.  
  162. #define ERROR_INDICATOR -1
  163. #define ILLEGAL_RELOC ERROR_INDICATOR
  164.  
  165. /* The following tables are indexed by [reloc_table_index(operand_format)] [field_selector]. */
  166.  
  167. int HPPA_ADDR_RELOC_TABLE [N_HPPA_FIELD_SELECTORS] [N_HPPA_OPERAND_FORMATS] = {
  168. /*      11               12            14              17             21        */
  169.   { R_HPPA_11,     ILLEGAL_RELOC, R_HPPA_14,     R_HPPA_17,     ILLEGAL_RELOC}, /* F% */
  170.   { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_L21},    /* L% */
  171.   { R_HPPA_R11,    ILLEGAL_RELOC, R_HPPA_R14,    R_HPPA_R17,    ILLEGAL_RELOC}, /* R% */
  172.   { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_LS21},   /* LS% */
  173.   { R_HPPA_RS11,   ILLEGAL_RELOC, R_HPPA_RS14,   R_HPPA_RS17,   ILLEGAL_RELOC}, /* RS% */
  174.   { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_LD21},   /* LD% */
  175.   { R_HPPA_RD11,   ILLEGAL_RELOC, R_HPPA_RD14,   R_HPPA_RD17    ILLEGAL_RELOC}, /* RD% */
  176.   { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_LR21},   /* LR% */
  177.   { ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_RR14,   R_HPPA_RR17,   ILLEGAL_RELOC}, /* RR% */
  178.   { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* T% */
  179.   { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* LT% */
  180.   { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* RT% */
  181.   { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* P% */
  182.   { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* LP% */
  183.   { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}  /* RD */
  184. };
  185.  
  186. int HPPA_GOTOFF_RELOC_TABLE [N_HPPA_FIELD_SELECTORS] [N_HPPA_OPERAND_FORMATS] = {
  187. /*        11                   12                 14                 17                  21        */
  188.   { R_HPPA_GOTOFF_11,   ILLEGAL_RELOC,      R_HPPA_GOTOFF_14,   ILLEGAL_RELOC,      ILLEGAL_RELOC},      /* F% */
  189.   { ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      R_HPPA_GOTOFF_L21},  /* L% */
  190.   { R_HPPA_GOTOFF_R11,  ILLEGAL_RELOC,      R_HPPA_GOTOFF_R14,  ILLEGAL_RELOC,      ILLEGAL_RELOC},      /* R% */
  191.   { ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      R_HPPA_GOTOFF_LS21}, /* LS% */
  192.   { R_HPPA_GOTOFF_RS11, ILLEGAL_RELOC,      R_HPPA_GOTOFF_RS14, ILLEGAL_RELOC,      ILLEGAL_RELOC},      /* RS% */
  193.   { ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      R_HPPA_GOTOFF_LD21}, /* LD% */
  194.   { R_HPPA_GOTOFF_RD11, ILLEGAL_RELOC,      R_HPPA_GOTOFF_RD14,  ILLEGAL_RELOC,      ILLEGAL_RELOC},      /* RD% */
  195.   { ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      R_HPPA_GOTOFF_LR21}, /* LR% */
  196.   { ILLEGAL_RELOC,       ILLEGAL_RELOC,     R_HPPA_GOTOFF_RR14, ILLEGAL_RELOC,      ILLEGAL_RELOC},      /* RR% */
  197.   { ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC},      /* T% */
  198.   { ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC},      /* LT% */
  199.   { ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC},      /* RT% */
  200.   { ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC},      /* P% */
  201.   { ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC},      /* LP% */
  202.   { ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC,      ILLEGAL_RELOC}       /* RP% */
  203. };
  204.  
  205. int HPPA_ABS_CALL_RELOC_TABLE [N_HPPA_FIELD_SELECTORS] [N_HPPA_OPERAND_FORMATS] = {
  206. /*         11                   12                      14                    17                  21        */
  207.   { R_HPPA_ABS_CALL_11,   ILLEGAL_RELOC,        R_HPPA_ABS_CALL_14,   R_HPPA_ABS_CALL_17,   ILLEGAL_RELOC},        /* F% */
  208.   { ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        R_HPPA_ABS_CALL_L21},  /* L% */
  209.   { R_HPPA_ABS_CALL_R11,  ILLEGAL_RELOC,        R_HPPA_ABS_CALL_R14,  R_HPPA_ABS_CALL_R17,  ILLEGAL_RELOC},        /* R% */
  210.   { ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        R_HPPA_ABS_CALL_LS21}, /* LS% */
  211.   { R_HPPA_ABS_CALL_RS11, ILLEGAL_RELOC,        R_HPPA_ABS_CALL_RS14, R_HPPA_ABS_CALL_RS17, ILLEGAL_RELOC},        /* RS% */
  212.   { ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        R_HPPA_ABS_CALL_LD21}, /* LD% */
  213.   { R_HPPA_ABS_CALL_RD11, ILLEGAL_RELOC,        R_HPPA_ABS_CALL_RD14, R_HPPA_ABS_CALL_RD17, ILLEGAL_RELOC},        /* RD% */
  214.   { ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        R_HPPA_ABS_CALL_LR21}, /* LR% */
  215.   { ILLEGAL_RELOC,        ILLEGAL_RELOC,        R_HPPA_ABS_CALL_RR14, R_HPPA_ABS_CALL_RR17, ILLEGAL_RELOC},        /* RR% */
  216.   { ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC},        /* T% */
  217.   { ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC},        /* LT% */
  218.   { ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC},        /* RT% */
  219.   { ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC},        /* P% */
  220.   { ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC},        /* LP% */
  221.   { ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC,        ILLEGAL_RELOC}         /* RP% */
  222. };
  223.  
  224. int HPPA_PCREL_CALL_RELOC_TABLE [N_HPPA_FIELD_SELECTORS] [N_HPPA_OPERAND_FORMATS] = {
  225. /*          11                      12                      14                      17                      21  */
  226.                                                                                                                    /* F% */
  227.   { R_HPPA_PCREL_CALL_11,   ILLEGAL_RELOC,        R_HPPA_PCREL_CALL_14,   R_HPPA_PCREL_CALL_17,   ILLEGAL_RELOC},
  228.                                                                                                                    /* L% */
  229.   { ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          R_HPPA_PCREL_CALL_L21},
  230.                                                                                                                    /* R% */
  231.   { R_HPPA_PCREL_CALL_R11,  ILLEGAL_RELOC,          R_HPPA_PCREL_CALL_R14,  R_HPPA_PCREL_CALL_R17,  ILLEGAL_RELOC},
  232.                                                                                                                    /* LS% */
  233.   { ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          R_HPPA_PCREL_CALL_LS21},
  234.                                                                                                                    /* RS% */
  235.   { R_HPPA_PCREL_CALL_RS11, ILLEGAL_RELOC,          R_HPPA_PCREL_CALL_RS14, R_HPPA_PCREL_CALL_RS17, ILLEGAL_RELOC},
  236.                                                                                                                    /* LD% */
  237.   { ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          R_HPPA_PCREL_CALL_LD21},
  238.                                                                                                                    /* RD% */
  239.   { R_HPPA_PCREL_CALL_RD11, ILLEGAL_RELOC,          R_HPPA_PCREL_CALL_RD14, R_HPPA_PCREL_CALL_RD17, ILLEGAL_RELOC},
  240.                                                                                                                    /* LR% */
  241.   { ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          R_HPPA_PCREL_CALL_LR21},
  242.                                                                                                                    /* RR% */
  243.   { ILLEGAL_RELOC,          ILLEGAL_RELOC,          R_HPPA_PCREL_CALL_RR14, R_HPPA_PCREL_CALL_RR17, ILLEGAL_RELOC},
  244.                                                                                                                    /* T% */
  245.   { ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC},
  246.                                                                                                                    /* LT% */
  247.   { ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC},
  248.                                                                                                                    /* RT% */
  249.   { ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC},
  250.                                                                                                                    /* P% */
  251.   { ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC},
  252.                                                                                                                    /* LP% */
  253.   { ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC},
  254.                                                                                                                    /* RP% */
  255.   { ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC,          ILLEGAL_RELOC}
  256. };
  257.  
  258. int HPPA_PLABEL_RELOC_TABLE [N_HPPA_FIELD_SELECTORS] [N_HPPA_OPERAND_FORMATS] = {
  259. /*         11                 12                 14                 17                 21  */
  260.   { ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC},     /* F% */
  261.   { ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC}, /* L% */
  262.   { ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC},     /* R% */
  263.   { ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC},     /* LS% */
  264.   { ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC},     /* RS% */
  265.   { ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC},     /* LD% */
  266.   { ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC},     /* RD% */
  267.   { ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC},     /* LR% */
  268.   { ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC},     /* RR% */
  269.   { ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC},     /* T% */
  270.   { ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC},     /* LT% */
  271.   { ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC},     /* RT% */
  272.   { R_HPPA_PLABEL_11,  ILLEGAL_RELOC,     R_HPPA_PLABEL_14,  ILLEGAL_RELOC,      ILLEGAL_RELOC},     /* P% */
  273.   { ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     ILLEGAL_RELOC,     R_HPPA_PLABEL_L21}, /* LP% */
  274.   { R_HPPA_PLABEL_R11, ILLEGAL_RELOC,     R_HPPA_PLABEL_R14, ILLEGAL_RELOC,    ILLEGAL_RELOC}      /* RP% */
  275. };
  276.  
  277.  
  278. static int reloc_table_idx();
  279.  
  280. #endif /* OBJ_ELF */
  281.  
  282. const relax_typeS md_relax_table[] = { 0 };
  283.  /* handle of the OPCODE hash table */
  284. static struct hash_control *op_hash = NULL;
  285.  
  286. int md_short_jump_size = 4;
  287. int md_long_jump_size = 4;
  288.  
  289. /* This array holds the chars that always start a comment.  If the
  290.     pre-processor is disabled, these aren't very useful */
  291. const char comment_chars[] = ";";    /* JF removed '|' from comment_chars */
  292.  
  293. const pseudo_typeS
  294. md_pseudo_table[] = {
  295.   { "align",    s_align_bytes,    0 }, /* .align 4 means .align to 4-byte boundary */
  296.   { "ALIGN",    s_align_bytes,    0 }, /* .align 4 means .align to 4-byte boundary */
  297.   { "block",    pa_block,    1 },
  298.   { "BLOCK",    pa_block,    1 },
  299.   { "blockz",    pa_block,    0 },
  300.   { "BLOCKZ",    pa_block,    0 },
  301.   { "call",    pa_call,    0 },
  302.   { "CALL",    pa_call,    0 },
  303.   { "callinfo",    pa_callinfo,    0 },
  304.   { "CALLINFO",    pa_callinfo,    0 },
  305.   { "code",    pa_code,    0 },
  306.   { "CODE",    pa_code,    0 },
  307.   { "comm",    pa_comm,    0 },
  308.   { "COMM",    pa_comm,    0 },
  309.   { "copyright",pa_copyright,    0 },
  310.   { "COPYRIGHT",pa_copyright,    0 },
  311.   { "end",    pa_end,        0 },
  312.   { "END",    pa_end,        0 },
  313.   { "enter",    pa_enter,    0 },
  314.   { "ENTER",    pa_enter,    0 },
  315.   { "entry",    pa_entry,    0 },
  316.   { "ENTRY",    pa_entry,    0 },
  317.   { "equ",    pa_equ,        0 },
  318.   { "EQU",    pa_equ,        0 },
  319.   { "exit",    pa_exit,    0 },
  320.   { "EXIT",    pa_exit,    0 },
  321.   { "export",    pa_export,    0 },
  322.   { "EXPORT",    pa_export,    0 },
  323.   { "half",    cons,        2 },
  324.   { "HALF",    cons,        2 },
  325.   { "import",    pa_import,    0 },
  326.   { "IMPORT",    pa_import,    0 },
  327.   { "label",    pa_label,    0 },
  328.   { "LABEL",    pa_label,    0 },
  329.   { "leave",    pa_leave,    0 },
  330.   { "LEAVE",    pa_leave,    0 },
  331.   { "origin",    pa_origin,    0 },
  332.   { "ORIGIN",    pa_origin,    0 },
  333.   { "proc",    pa_proc,    0 },
  334.   { "PROC",    pa_proc,    0 },
  335.   { "procend",    pa_procend,    0 },
  336.   { "PROCEND",    pa_procend,    0 },
  337.   { "reg",    pa_equ,        1 },      /* very similar to .equ */
  338.   { "REG",    pa_equ,        1 },      /* very similar to .equ */
  339.   { "space",    pa_space,    0 },
  340.   { "SPACE",    pa_space,    0 },
  341.   { "spnum",    pa_spnum,    0 },
  342.   { "SPNUM",    pa_spnum,    0 },
  343.   { "string",    stringer,    0 },
  344.   { "STRING",    stringer,    0 },
  345.   { "stringz",    stringer,    1 },
  346.   { "STRINGZ",    stringer,    1 },
  347.   { "subspa",    pa_subspace,    0 },
  348.   { "SUBSPA",    pa_subspace,    0 },
  349.   { "word",    cons,        4 },
  350.   { "WORD",    cons,        4 },
  351.   { NULL,    0,        0 }
  352. };
  353.  
  354. /* This array holds the chars that only start a comment at the beginning of
  355.    a line.  If the line seems to have the form '# 123 filename'
  356.    .line and .file directives will appear in the pre-processed output */
  357. /* Note that input_file.c hand checks for '#' at the beginning of the
  358.    first line of the input file.  This is because the compiler outputs
  359.    #NO_APP at the beginning of its output. */
  360. /* Also note that '/*' will always start a comment */
  361. const char line_comment_chars[] = "#";
  362.  
  363. const char line_separator_chars[] = "!";
  364.  
  365. /* Chars that can be used to separate mant from exp in floating point nums */
  366. const char EXP_CHARS[] = "eE";
  367.  
  368. /* Chars that mean this number is a floating point constant */
  369. /* As in 0f12.456 */
  370. /* or    0d1.2345e12 */
  371. const char FLT_CHARS[] = "rRsSfFdDxXpP";
  372.  
  373. /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
  374.    changed in read.c .  Ideally it shouldn't have to know about it at all,
  375.    but nothing is ideal around here.
  376.  */
  377.  
  378. static unsigned char octal[256];
  379. #ifndef isoctal
  380. #define isoctal(c)  octal[c]
  381. #endif
  382. static unsigned char toHex[256];
  383.  
  384. struct pa_it set_insn;   /* this structure is defined above */
  385.  
  386. /* SKV 12/22/92.  Added prev_insn, prev_fix, and initialized the_insn
  387.    so that we can recognize instruction sequences such as (ldil, ble)
  388.    and generate the appropriate fixups. */
  389.  
  390. struct pa_it the_insn = {
  391.     NULL,         /* error */
  392.     0,            /* opcode */
  393.     NULL,         /* nlistp */
  394.     {
  395.       NULL,       /* exp.X_add_symbol */
  396.       NULL,       /* exp.X_subtract_symbol */
  397.       0,          /* exp.X_add_number */
  398.       NULL        /* exp.asection */
  399.     },
  400.     0,            /* pcrel */
  401.     0,            /* fpof1 */
  402.     0,            /* fpof2 */
  403.     0,            /* reloc */
  404.     0,            /* field_selector */
  405.     0,            /* code */
  406.     0,            /* arg_reloc */
  407.     {             /* unwind */
  408.       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  409.     }
  410.   };
  411.  
  412. #ifdef OBJ_ELF
  413.  
  414. struct pa_it prev_insn;
  415. char prev_str[10] = "";
  416. fixS *prev_fix = NULL;
  417. fixS *curr_fix = NULL;
  418.  
  419. #endif /* OBJ_ELF */
  420.  
  421. #ifdef __STDC__
  422. void print_insn(struct pa_it *insn);
  423. #else
  424. void print_insn();
  425. #endif
  426. char *expr_end;
  427.  
  428. symbolS *label_symbolP;       /* the last label symbol encountered */
  429.                               /* saved here in case a .equ is encountered */
  430. int label_symbol_defined;
  431.  
  432. int callinfo_found;           /* T if a .callinfo appeared within the current */
  433.                               /*  procedure definition and F otherwise        */
  434.  
  435. int within_entry_exit;        /* T if the assembler is currently within a     */
  436.                               /* .entry/.exit pair and F otherwise            */
  437.  
  438. int exit_processing_complete; /* T is the assembler has completed exit */
  439.                               /* processing for the current procedure  */
  440.                               /* and F otherwise                       */
  441.  
  442. int within_procedure;         /* T if the assembler is currently within a  */
  443.                               /* a procedure definition and F otherwise    */
  444.  
  445. void ignore_rest_of_line();   /* a useful function in read.c */
  446.  
  447. /* default space and subspace dictionaries */
  448.  
  449. #define GDB_SYMBOLS          GDB_SYMBOLS_SUBSPACE_NAME
  450. #define GDB_STRINGS          GDB_STRINGS_SUBSPACE_NAME
  451.  
  452. #if defined(OBJ_ELF)
  453. struct default_subspace_dict pa_def_subspaces[] =
  454. {
  455.   { "$CODE$",  0, 1, 0, 0, 0, 0, 24, 0x2c, 0, 8, 0, 0, SUBSEG_CODE   },
  456.   { "$DATA$",  0, 1, 0, 0, 0, 0, 24, 0x1f, 0, 8, 1, 1, SUBSEG_DATA   },
  457.   { "$LIT$",   0, 1, 0, 0, 0, 0, 16, 0x2c, 0, 8, 0, 0, SUBSEG_LIT    },
  458.   { "$BSS$",   0, 1, 0, 0, 0, 1, 80, 0x1f, 0, 8, 1, 1, SUBSEG_BSS    },
  459.   { "$UNWIND$",0, 1, 0, 0, 0, 0, 64, 0x2c, 0, 4, 0, 0, SUBSEG_UNWIND },
  460.   { GDB_STRINGS,0,0, 0, 0, 0, 0,254, 0x1f, 0, 4, 0, 2, SUBSEG_GDB_STRINGS },
  461.   { GDB_SYMBOLS,0,0, 0, 0, 0, 0,255, 0x1f, 0, 4, 0, 2, SUBSEG_GDB_SYMBOLS },
  462.   { NULL,      0, 1, 0, 0, 0, 0,255, 0x1f, 0, 4, 0, 0, 0 }
  463. };
  464.  
  465. struct default_space_dict pa_def_spaces[] =
  466. {
  467.   { "$TEXT$",                   0, 1, 0, 0,   8, ASEC_NULL,    ".text" },
  468.   { "$PRIVATE$",                0, 1, 0, 0,  16, ASEC_NULL,    ".data"    },
  469.   { GDB_DEBUG_SPACE_NAME,       0, 0, 0, 0, 255, ASEC_NULL,    NULL /* ".debug" */ },
  470.   { NULL,                       0, 0, 0, 0,   0, ASEC_NULL,    NULL    }
  471. };
  472. #else
  473. struct default_subspace_dict pa_def_subspaces[] =
  474. {
  475.   { "$CODE$",  0, 1, 0, 0, 0, 0, 24, 0x2c, 0, 8, 0, SEG_TEXT, SUBSEG_CODE   },
  476.   { "$DATA$",  0, 1, 0, 0, 0, 0, 24, 0x1f, 0, 8, 1, SEG_DATA, SUBSEG_DATA   },
  477.   { "$LIT$",   0, 1, 0, 0, 0, 0, 16, 0x2c, 0, 8, 0, SEG_TEXT, SUBSEG_LIT    },
  478.   { "$BSS$",   0, 1, 0, 0, 0, 1, 80, 0x1f, 0, 8, 1, SEG_DATA, SUBSEG_BSS    },
  479.   { "$UNWIND$",0, 1, 0, 0, 0, 0, 64, 0x2c, 0, 4, 0, SEG_TEXT, SUBSEG_UNWIND },
  480.   { GDB_STRINGS,0,0, 0, 0, 0, 0,254, 0x1f, 0, 4, 0, SEG_GDB,  SUBSEG_GDB_STRINGS
  481.  },
  482.   { GDB_SYMBOLS,0,0, 0, 0, 0, 0,255, 0x1f, 0, 4, 0, SEG_GDB,  SUBSEG_GDB_SYMBOLS
  483.  },
  484.   { NULL,0,1,0,0,0,0,255,0x1f,0,4,0,SEG_GOOF,0 }
  485. };
  486.  
  487. struct default_space_dict pa_def_spaces[] =
  488. {
  489.   { "$TEXT$",                   0, 1, 0, 0,   8, SEG_TEXT},
  490.   { "$PRIVATE$",                0, 1, 0, 0,  16, SEG_DATA},
  491.   { GDB_DEBUG_SPACE_NAME,       0, 0, 0, 0, 255, SEG_GDB},
  492.   { NULL,                       0, 0, 0, 0,   0, SEG_GOOF}
  493. };
  494. #endif
  495.  
  496. #ifdef USG
  497. #define bcmp(b1,b2,n) memcmp((b1),(b2),(n))
  498. #define index strchr
  499. #endif
  500.  
  501. #ifndef FALSE
  502. #define FALSE   (0)
  503. #define TRUE    (!FALSE)
  504. #endif /* no FALSE yet */
  505.  
  506. /*
  507.     Support for keeping track of the most recent label in each
  508.     space.
  509.  */
  510.  
  511. /*
  512.     PA_PSEUDO_OP_MOVES_PC
  513.  
  514.     A predicate that returns true if the pseudo-operation or
  515.     assembly directive results in a movement in the current
  516.     location.  All instructions cause movement in the current
  517.     location.
  518.  */
  519.  
  520. static const char * movers[] = {
  521.       /* these entries from 'static pseudo_typeS potable[]' in pa-read.c */
  522.     "ascii",    "asciz",
  523.     "byte",
  524.     "comm",
  525.     "data",        "desc",        "double",
  526.     "fill",        "float",
  527.     "globl",
  528.     "half",
  529.     "int",
  530.     "lcomm",    "long",        "lsym",
  531.     "octa",        "org",
  532.     "quad",
  533.     "short",    "single",
  534.     "text",
  535.     "word",
  536.   /* these entries from 'pseudo_typeS md_pseudo_table[]' in pa-aux.c */
  537.     "block",    "blockz",
  538.     "code",        "copyright",
  539.     "equ",
  540.     "origin",
  541.     "reg",      /* very similar to .equ */
  542.     "string",    "stringz",
  543.     "version",
  544.     NULL    /* end sentinel */
  545. };
  546.  
  547. int
  548. pa_pseudo_op_moves_pc(name)
  549. char * name;
  550. {
  551.     int i = 0;
  552.     while ( movers[i] ) {
  553.         if ( strcmp(name,movers[i++]) == 0 )
  554.             return 1;
  555.     }
  556.  
  557.     return 0;
  558. }
  559.  
  560. /*
  561.     Support for keeping track of the most recent label in each
  562.     space.
  563.  */
  564.  
  565. /* XXX:  NOTE:  label_symbolS is defined in pa.h */
  566.  
  567. label_symbolS *label_symbols_rootP = NULL;
  568.  
  569. /*
  570.     PA_GET_LABEL
  571.  
  572.     Returns a pointer to the label_symbolS for the current space.
  573.  */
  574.  
  575. label_symbolS *
  576. pa_get_label()
  577. {
  578.     label_symbolS *lssP;
  579.     space_dict_chainS *now_sdcP = pa_segment_to_space(now_seg);
  580.  
  581.     for ( lssP = label_symbols_rootP; lssP; lssP = lssP->lss_next ) {
  582.         if ( now_sdcP == lssP->lss_space && lssP->lss_label )
  583.             return lssP;
  584.     }
  585.  
  586.     return (label_symbolS *)NULL;
  587. }
  588.  
  589. /*
  590.     PA_LABEL_IS_DEFINED
  591.  
  592.     A predicate to determine whether a useable label is defined in
  593.     the current space.
  594.  */
  595.  
  596. int
  597. pa_label_is_defined()
  598. {
  599.     return (int)pa_get_label();
  600. }
  601.  
  602. /*
  603.     PA_DEFINE_LABEL
  604.  
  605.     Defines a label for the current space.  If one is already defined,
  606.     this function will replace it with the new label.
  607.  */
  608.  
  609. void
  610. pa_define_label(symbolP)
  611. symbolS * symbolP;
  612. {
  613.     label_symbolS *lssP        = pa_get_label();
  614.     space_dict_chainS *now_sdcP    = pa_segment_to_space(now_seg);
  615.  
  616.     if ( lssP ) {
  617.         lssP->lss_label = symbolP;
  618.     }
  619.     else {
  620.         lssP = (label_symbolS *)xmalloc(sizeof(label_symbolS));
  621.         lssP->lss_label    = symbolP;
  622.         lssP->lss_space    = now_sdcP;
  623.         lssP->lss_next    = (label_symbolS *)NULL;
  624.  
  625.         if ( label_symbols_rootP ) {
  626.             lssP->lss_next    = label_symbols_rootP;
  627.         }
  628.         label_symbols_rootP    = lssP;
  629.     }
  630. }
  631.  
  632. /*
  633.     PA_UNDEFINE_LABEL
  634.  
  635.     Removes a label definition for the current space.
  636.     If there is no label_symbolS entry, then no action is taken.
  637.  */
  638.  
  639. void
  640. pa_undefine_label()
  641. {
  642.     label_symbolS *lssP;
  643.     label_symbolS *prevP = (label_symbolS *)NULL;
  644.     space_dict_chainS *now_sdcP = pa_segment_to_space(now_seg);
  645.  
  646.     for ( lssP = label_symbols_rootP; lssP; lssP = lssP->lss_next ) {
  647.         if ( now_sdcP == lssP->lss_space && lssP->lss_label ) {
  648.             if ( prevP )
  649.                 prevP->lss_next = lssP->lss_next;
  650.             else
  651.                 label_symbols_rootP = lssP->lss_next;
  652.  
  653.             free(lssP);
  654.             break;
  655.         }
  656.         prevP = lssP;
  657.     }
  658. }
  659.  
  660. /* end of label symbol support. */
  661.  
  662.  
  663. /* An HPPA-specific version of fix_new.  This is required because the HPPA    */
  664. /* code needs to keep track of some extra stuff.  Each call to fix_new_hppa    */
  665. /* results in the creation of an instance of an hppa_fixS.  An hppa_fixS    */
  666. /* stores the extra information along with a pointer to the original fixS.    */
  667.  
  668. typedef struct hppa_fix_struct {
  669.     fixS   *fx_fixP;
  670.     int    fx_r_field;
  671.     int    fx_r_type;
  672.     int    fx_r_format;
  673.     long    fx_arg_reloc;
  674.     call_infoS *fx_call_infop;
  675.     char    fx_unwind[8];
  676.     struct hppa_fix_struct *fx_next;
  677. } hppa_fixS;
  678.  
  679. hppa_fixS * hppa_fix_root = NULL;
  680.  
  681. void fix_new_hppa(frag, where, size, add_symbol, sub_symbol, offset, pcrel,
  682.           r_type, r_field, r_format, arg_reloc, unwind_desc)
  683.      fragS    *frag;        /* Which frag? */
  684.      int    where;        /* Where in that frag? */
  685.      short int    size;        /* 1, 2  or 4 usually. */
  686.      symbolS    *add_symbol;    /* X_add_symbol. */
  687.      symbolS    *sub_symbol;    /* X_subtract_symbol. */
  688.      long    offset;        /* X_add_number. */
  689.      int    pcrel;        /* TRUE if PC-relative relocation. */
  690.      enum reloc_type r_type;    /* Relocation type */
  691.      long       r_field;        /* F, R, L, etc */
  692.      int        r_format;    /* 11,12,14,17,21,32, etc */
  693.      long       arg_reloc;
  694.      char       *unwind_desc;
  695. {
  696.     fixS *new_fix = fix_new(frag, where, size,
  697.                 add_symbol, sub_symbol,
  698.                 offset, pcrel, r_type);
  699.  
  700.     hppa_fixS *hppa_fix = (hppa_fixS *)obstack_alloc(¬es,sizeof(hppa_fixS));
  701.  
  702.     hppa_fix->fx_fixP    = new_fix;
  703.     hppa_fix->fx_r_field    = r_field;
  704.     hppa_fix->fx_r_format    = r_format;
  705.     hppa_fix->fx_arg_reloc    = arg_reloc;
  706.     hppa_fix->fx_next    = (hppa_fixS *)0;
  707.     hppa_fix->fx_call_infop    = last_call_info;
  708.     if (unwind_desc)
  709.         bcopy(unwind_desc, hppa_fix->fx_unwind, 8);
  710.  
  711.     if ( hppa_fix_root )
  712.         hppa_fix->fx_next = hppa_fix_root;
  713.  
  714.     hppa_fix_root = hppa_fix;
  715.  
  716. /* SKV 12/22/92.  Added prev_insn, prev_fix, and initialized the_insn
  717.    so that we can recognize instruction sequences such as (ldil, ble)
  718.    and generate the appropriate fixups. */
  719.  
  720. #ifdef OBJ_ELF
  721.  
  722.     curr_fix = new_fix;
  723.  
  724. #endif /* OBJ_ELF */
  725. }
  726.  
  727. /* Given a FixS, find the hppa_fixS associated with it. */
  728. hppa_fixS *
  729.     hppa_find_hppa_fix(fix)
  730. fixS *fix;
  731. {
  732.     hppa_fixS *hfP;
  733.  
  734.     for ( hfP = hppa_fix_root; hfP; hfP = hfP->fx_next ) {
  735.         if ( hfP->fx_fixP == fix )
  736.             return hfP;
  737.     }
  738.  
  739.     return (hppa_fixS *)0;
  740. }
  741.  
  742. /* This function is called once, at assembler startup time.  It should
  743.    set up all the tables, etc. that the MD part of the assembler will need.  */
  744. void
  745. md_begin()
  746. {
  747.   register char *retval = NULL;
  748.   int lose = 0;
  749.   register unsigned int i = 0;
  750.  
  751.   last_call_info = NULL;
  752.   call_info_root = NULL;
  753.  
  754.   pa_spaces_begin();
  755.  
  756.   op_hash = hash_new();
  757.   if (op_hash == NULL)
  758.     as_fatal("Virtual memory exhausted");
  759.  
  760.   while (i < NUMOPCODES)
  761.     {
  762.       const char *name = pa_opcodes[i].name;
  763.       retval = hash_insert(op_hash, name, &pa_opcodes[i]);
  764.       if(retval != NULL && *retval != '\0')
  765.     {
  766.       as_fatal("Internal error: can't hash `%s': %s\n",
  767.            pa_opcodes[i].name, retval);
  768.       lose = 1;
  769.     }
  770.       do
  771.     {
  772.       if ( (pa_opcodes[i].match & pa_opcodes[i].mask) != pa_opcodes[i].match )
  773.         {
  774.           fprintf(stderr, "internal error: losing opcode: `%s' \"%s\"\n",
  775.                pa_opcodes[i].name, pa_opcodes[i].args);
  776.           lose = 1;
  777.         }
  778.       ++i;
  779.     } while (i < NUMOPCODES
  780.          && !strcmp(pa_opcodes[i].name, name));
  781.     }
  782.  
  783.   if (lose)
  784.     as_fatal ("Broken assembler.  No assembly attempted.");
  785.  
  786.   for (i = '0'; i < '8'; ++i)
  787.     octal[i] = 1;
  788.   for (i = '0'; i <= '9'; ++i)
  789.     toHex[i] = i - '0';
  790.   for (i = 'a'; i <= 'f'; ++i)
  791.     toHex[i] = i + 10 - 'a';
  792.   for (i = 'A'; i <= 'F'; ++i)
  793.     toHex[i] = i + 10 - 'A';
  794.  
  795. }
  796.  
  797. void
  798. md_end()
  799. {
  800.     return;
  801. }
  802.  
  803. void
  804. md_assemble(str)
  805.     char *str;
  806. {
  807.     char *toP;
  808.  
  809.     assert(str);
  810.     pa_ip(str);
  811.     toP = frag_more(4);
  812.     /* put out the opcode */
  813.     md_number_to_chars(toP, the_insn.opcode, 4);
  814.  
  815.     /* put out the symbol-dependent stuff */
  816. #if defined ( OBJ_SOM )
  817.     if (the_insn.reloc != R_NO_RELOCATION) {
  818. #elif defined ( OBJ_ELF )
  819.     if (the_insn.reloc != R_HPPA_NONE) {        
  820. #endif
  821.  
  822. #if defined(OBJ_ELF)
  823.     fix_new_hppa(frag_now,                           /* which frag */
  824.              (toP - frag_now->fr_literal), /* where */
  825.              4,                                  /* size */
  826.              the_insn.exp.X_add_symbol,
  827.              the_insn.exp.X_subtract_symbol,
  828.              the_insn.exp.X_add_number,
  829.              the_insn.pcrel,
  830.              the_insn.reloc,
  831.              the_insn.field_selector,
  832.              the_insn.format,
  833.              the_insn.arg_reloc,
  834.              (char *) 0 );
  835. #endif
  836. #ifdef OBJ_SOM
  837.     fix_new(frag_now,                           /* which frag */
  838.         (toP - frag_now->fr_literal), /* where */
  839.         4,                                  /* size */
  840.         the_insn.exp.X_add_symbol,
  841.         the_insn.exp.X_subtract_symbol,
  842.         the_insn.exp.X_add_number,
  843.         the_insn.pcrel,
  844.         the_insn.reloc,
  845.         the_insn.field_selector,
  846.         the_insn.code,
  847.         the_insn.arg_reloc,
  848.         (char *) 0 );
  849. #endif
  850.     }
  851.  
  852. /* SKV 12/22/92.  Added prev_insn, prev_fix, and initialized the_insn
  853.    so that we can recognize instruction sequences such as (ldil, ble)
  854.    and generate the appropriate fixups. */
  855.  
  856. #ifdef OBJ_ELF
  857.  
  858.     prev_insn = the_insn;
  859.     strncpy(prev_str, str, 10);
  860.     if (prev_insn.reloc = R_HPPA_NONE)
  861.       {
  862.          prev_fix = NULL;
  863.       }
  864.     else
  865.       {
  866.          prev_fix = curr_fix;
  867.       }
  868.  
  869. #endif /* OBJ_ELF */
  870. }
  871.  
  872. static void
  873. pa_ip(str)
  874.     char *str;
  875. {
  876.     char *error_message = "";
  877.     char *s;
  878.     const char *args;
  879.     char c;
  880.     unsigned long i;
  881.     struct pa_opcode *insn;
  882.     char *argsStart;
  883.     unsigned long   opcode;
  884.     unsigned int mask;
  885.     int match = FALSE;
  886.     int comma = 0;
  887.  
  888.     int reg,reg1,reg2,s2,s3;
  889.     unsigned int im21,im14,im11,im5;
  890.     int m,a,uu,f;
  891.     int cmpltr,nullif, flag;
  892.     int sfu, cond;
  893.     char *name;
  894.     char *p, *save_s;
  895.  
  896. #ifdef PA_DEBUG
  897.     fprintf(stderr,"STATEMENT: \"%s\"\n",str);
  898. #endif
  899.     for (s = str; isupper(*s) || islower(*s) || (*s >= '0' && *s <= '3'); ++s)
  900.     ;
  901.     switch (*s) {
  902.  
  903.     case '\0':
  904.     break;
  905.  
  906.     case ',':
  907.     comma = 1;
  908.  
  909.     /*FALLTHROUGH*/
  910.  
  911.     case ' ':
  912.     *s++ = '\0';
  913.     break;
  914.  
  915.     default:
  916.         as_bad("Unknown opcode: `%s'", str);
  917.         exit(1);
  918.     }
  919.  
  920.     save_s = str;
  921.  
  922.     while ( *save_s ) {
  923.       if ( isupper(*save_s) )
  924.     *save_s = tolower(*save_s);
  925.       save_s++;
  926.     }
  927.  
  928.     if ((insn = (struct pa_opcode *) hash_find(op_hash, str)) == NULL) {
  929.     as_bad("Unknown opcode: `%s'", str);
  930.     return;
  931.     }
  932.     if (comma) {
  933.     *--s = ',';
  934.     }
  935.     argsStart = s;
  936.     for (;;) {
  937.     opcode = insn->match;
  938.     bzero(&the_insn, sizeof(the_insn));
  939. #if defined( OBJ_SOM )
  940.     the_insn.reloc = R_NO_RELOCATION;
  941. #else
  942. #if defined ( OBJ_ELF )
  943.     the_insn.reloc = R_HPPA_NONE;
  944. #endif
  945. #endif
  946.     /*
  947.      * Build the opcode, checking as we go to make
  948.      * sure that the operands match
  949.      */
  950.     for (args = insn->args; ; ++args) {
  951.  
  952.         switch (*args) {
  953.  
  954.         case '\0':  /* end of args */
  955.           if (*s == '\0') {
  956.         match = TRUE;
  957.           }
  958.           break;
  959.  
  960.         case '+':
  961.           if (*s == '+') {
  962.         ++s;
  963.         continue;
  964.           }
  965.           if (*s == '-') {
  966.         continue;
  967.           }
  968.           break;
  969.  
  970.         case '(':   /* these must match exactly */
  971.         case ')':
  972.         case ',':
  973.         case ' ':
  974.           if (*s++ == *args)
  975.         continue;
  976.           break;
  977.  
  978.         case 'b':   /* 5 bit register field at 10 */
  979.         case '^':   /* 5 bit control register field at 10 */
  980.           reg = pa_parse_number(&s);
  981.           if ( reg < 32 && reg >= 0 ) {
  982.         opcode |= reg << 21;
  983.         continue;
  984.           }
  985.           break;
  986.         case 'x':   /* 5 bit register field at 15 */
  987.           reg = pa_parse_number(&s);
  988.           if ( reg < 32 && reg >= 0 ) {
  989.         opcode |= reg << 16;
  990.         continue;
  991.           }
  992.           break;
  993.         case 't':   /* 5 bit register field at 31 */
  994.           reg = pa_parse_number(&s);
  995.           if ( reg < 32 && reg >= 0 ) {
  996.         opcode |= reg;
  997.         continue;
  998.           }
  999.           break;
  1000.         case 'T':   /* 5 bit field length at 31 (encoded as 32-T) */
  1001.           /*
  1002.         reg = pa_parse_number(&s);
  1003.            */
  1004.           getAbsoluteExpression(s);
  1005.           if ( the_insn.exp.X_seg == &bfd_abs_section ) {
  1006.         reg = the_insn.exp.X_add_number;
  1007.         if ( reg <= 32 && reg > 0 ) {
  1008.           opcode |= 32 - reg;
  1009.           s = expr_end;
  1010.           continue;
  1011.         }
  1012.           }
  1013.           break;
  1014.         case '5':   /* 5 bit immediate at 15 */
  1015.           getAbsoluteExpression(s);
  1016.           /** PJH: The following 2 calls to as_bad() might eventually **/
  1017.           /**      want to end up as as_warn().  **/
  1018.           if (   the_insn.exp.X_add_number > 15 ) {
  1019.         as_bad("5 bit immediate > 15. Set to 15",
  1020.                the_insn.exp.X_add_number);
  1021.         the_insn.exp.X_add_number = 15;
  1022.           }
  1023.           else if ( the_insn.exp.X_add_number < -16 ) {
  1024.         as_bad("5 bit immediate < -16. Set to -16",
  1025.                the_insn.exp.X_add_number);
  1026.         the_insn.exp.X_add_number = -16;
  1027.           }
  1028.  
  1029.           low_sign_unext(evaluateAbsolute(the_insn.exp,the_insn.field_selector),
  1030.                  5,&im5);
  1031.           opcode |= ( im5 << 16 );
  1032.           s = expr_end;
  1033.           continue;
  1034.  
  1035.         case 's':   /* 2 bit space identifier at 17 */
  1036.           s2 = pa_parse_number(&s);
  1037.           if ( s2 < 4 && s2 >= 0 ) {
  1038.         opcode |= s2 << 14;
  1039.         continue;
  1040.           }
  1041.           break;
  1042.         case 'S':   /* 3 bit space identifier at 18 */
  1043.           s3 = pa_parse_number(&s);
  1044.           if ( s3 < 8 && s3 >= 0 ) {
  1045.         dis_assemble_3(s3,&s3);
  1046.         opcode |= s3 << 13;
  1047.         continue;
  1048.           }
  1049.           break;
  1050.         case 'c':   /* indexed load completer. */
  1051.           uu = 0;
  1052.           m = 0;
  1053.           i = 0;
  1054.           while ( *s == ',' && i < 2 ) {
  1055.         s++;
  1056.         if ( strncasecmp(s,"sm",2) == 0 ) {
  1057.           uu = 1;
  1058.           m = 1;
  1059.           s++;
  1060.           i++;
  1061.         }
  1062.         else if ( strncasecmp(s,"m",1) == 0 )
  1063.           m = 1;
  1064.         else if ( strncasecmp(s,"s",1) == 0 )
  1065.           uu = 1;
  1066.         else
  1067.           as_bad("Unrecognized Indexed Load Completer...assuming 0");
  1068.         s++;
  1069.         i++;
  1070.           }
  1071.           if ( i > 2 )
  1072.         as_bad("Illegal Indexed Load Completer Syntax...extras ignored");
  1073.           /* pa_skip(&s); */
  1074.           while ( *s == ' ' || *s == '\t' )
  1075.         s++;
  1076.           
  1077.           opcode |= m << 5;
  1078.           opcode |= uu << 13;
  1079.           continue;
  1080.         case 'C':   /* short load and store completer */
  1081.           a = 0;
  1082.           m = 0;
  1083.           if ( *s == ',' ) {
  1084.         s++;
  1085.         if ( strncasecmp(s,"ma",2) == 0 ) {
  1086.           a = 0;
  1087.           m = 1;
  1088.         }
  1089.         else if ( strncasecmp(s,"mb",2) == 0 ) {
  1090.           a = 1;
  1091.           m = 1;
  1092.         }
  1093.         else
  1094.           as_bad("Unrecognized Indexed Load Completer...assuming 0");
  1095.         s += 2;
  1096.           }
  1097.           /* pa_skip(&s); */
  1098.           while ( *s == ' ' || *s == '\t' )
  1099.         s++;
  1100.           opcode |= m << 5;
  1101.           opcode |= a << 13;
  1102.           continue;
  1103.         case 'Y':   /* Store Bytes Short completer */
  1104.           a = 0;
  1105.           m = 0;
  1106.           i = 0;
  1107.           while ( *s == ',' && i < 2 ) {
  1108.         s++;
  1109.         if ( strncasecmp(s,"m",1) == 0 )
  1110.           m = 1;
  1111.         else if ( strncasecmp(s,"b",1) == 0 )
  1112.           a = 0;
  1113.         else if ( strncasecmp(s,"e",1) == 0 )
  1114.           a = 1;
  1115.         else
  1116.           as_bad("Unrecognized Store Bytes Short Completer...assuming 0");
  1117.         s++;
  1118.         i++;
  1119.           }
  1120.           /**        if ( i >= 2 ) **/
  1121.           if ( i > 2 )
  1122.         as_bad("Illegal Store Bytes Short Completer...extras ignored");
  1123.           while ( *s == ' ' || *s == '\t' ) /* skip to next operand */
  1124.         s++;
  1125.           opcode |= m << 5;
  1126.           opcode |= a << 13;
  1127.           continue;
  1128.         case '<':   /* non-negated compare/subtract conditions. */
  1129.           cmpltr = pa_parse_nonneg_cmpsub_cmpltr(&s);
  1130.           if ( cmpltr < 0 ) {
  1131.         as_bad("Unrecognized Compare/Subtract Condition: %c",*s);
  1132.         cmpltr = 0;
  1133.           }
  1134.           opcode |= cmpltr << 13;
  1135.           continue;
  1136.         case '?':   /* negated or non-negated cmp/sub conditions. */
  1137.           /* used only by ``comb'' and ``comib'' pseudo-ops */
  1138.           save_s = s;
  1139.           cmpltr = pa_parse_nonneg_cmpsub_cmpltr(&s);
  1140.           if ( cmpltr < 0 ) {
  1141.         s = save_s;
  1142.         cmpltr = pa_parse_neg_cmpsub_cmpltr(&s);
  1143.         if ( cmpltr < 0 ) {
  1144.           as_bad("Unrecognized Compare/Subtract Condition: %c",*s);
  1145.           cmpltr = 0;
  1146.         }
  1147.         else {
  1148.           opcode |= 1 << 27; /* required opcode change to make
  1149.                                 COMIBT into a COMIBF or a
  1150.                                 COMBT into a COMBF or a
  1151.                             ADDBT into a ADDBF or a
  1152.                             ADDIBT into a ADDIBF */
  1153.         }
  1154.           }
  1155.           opcode |= cmpltr << 13;
  1156.           continue;
  1157.         case '!':   /* negated or non-negated add conditions. */
  1158.           /* used only by ``addb'' and ``addib'' pseudo-ops */
  1159.           save_s = s;
  1160.           cmpltr = pa_parse_nonneg_add_cmpltr(&s);
  1161.           if ( cmpltr < 0 ) {
  1162.         s = save_s;
  1163.         cmpltr = pa_parse_neg_add_cmpltr(&s);
  1164.         if ( cmpltr < 0 ) {
  1165.           as_bad("Unrecognized Compare/Subtract Condition: %c",*s);
  1166.           cmpltr = 0;
  1167.         }
  1168.         else {
  1169.           opcode |= 1 << 27; /* required opcode change to make
  1170.             COMIBT into a COMIBF or a
  1171.               COMBT into a COMBF or a
  1172.             ADDBT into a ADDBF or a
  1173.               ADDIBT into a ADDIBF */
  1174.         }
  1175.           }
  1176.           opcode |= cmpltr << 13;
  1177.           continue;
  1178.         case 'a':   /* compare/subtract conditions */
  1179.           cmpltr = 0;
  1180.           f = 0;
  1181.           save_s = s;
  1182.           if ( *s == ',' ) {
  1183.         cmpltr = pa_parse_nonneg_cmpsub_cmpltr(&s);
  1184.         if ( cmpltr < 0 ) {
  1185.           f = 1;
  1186.           s = save_s;
  1187.           cmpltr = pa_parse_neg_cmpsub_cmpltr(&s);
  1188.           if ( cmpltr < 0 ) {
  1189.             as_bad("Unrecognized Compare/Subtract Condition");
  1190.           }
  1191.         }
  1192.           }
  1193.           opcode |= cmpltr << 13;
  1194.           opcode |= f << 12;
  1195.           continue;
  1196.         case 'd':   /* non-negated add conditions */
  1197.           cmpltr = 0;
  1198.           nullif = 0;
  1199.           flag   = 0;
  1200.           if ( *s == ',' ) {
  1201.         s++;
  1202.         name = s;
  1203.         while ( *s != ',' && *s != ' ' && *s != '\t' )
  1204.           s += 1;
  1205.         c = *s;
  1206.         *s = 0x00;
  1207.         if ( strcmp(name,"=") == 0 ) {
  1208.           cmpltr = 1;
  1209.         }
  1210.         else if ( strcmp(name,"<") == 0 ) {
  1211.           cmpltr = 2;
  1212.         }
  1213.         else if ( strcmp(name,"<=") == 0 ) {
  1214.           cmpltr = 3;
  1215.         }
  1216.         else if ( strcasecmp(name,"nuv") == 0 ) {
  1217.           cmpltr = 4;
  1218.         }
  1219.         else if ( strcasecmp(name,"znv") == 0 ) {
  1220.           cmpltr = 5;
  1221.         }
  1222.         else if ( strcasecmp(name,"sv") == 0 ) {
  1223.           cmpltr = 6;
  1224.         }
  1225.         else if ( strcasecmp(name,"od") == 0 ) {
  1226.           cmpltr = 7;
  1227.         }
  1228.         else if ( strcasecmp(name,"n") == 0 ) {
  1229.           nullif = 1;
  1230.         }
  1231.         else if ( strcasecmp(name,"tr") == 0 ) {
  1232.           cmpltr = 0;
  1233.           flag   = 1;
  1234.         }
  1235.         else if ( strcasecmp(name,"<>") == 0 ) {
  1236.           cmpltr = 1;
  1237.           flag   = 1;
  1238.         }
  1239.         else if ( strcasecmp(name,">=") == 0 ) {
  1240.           cmpltr = 2;
  1241.           flag   = 1;
  1242.         }
  1243.         else if ( strcasecmp(name,">") == 0 ) {
  1244.           cmpltr = 3;
  1245.           flag   = 1;
  1246.         }
  1247.         else if ( strcasecmp(name,"uv") == 0 ) {
  1248.           cmpltr = 4;
  1249.           flag   = 1;
  1250.         }
  1251.         else if ( strcasecmp(name,"vnz") == 0 ) {
  1252.           cmpltr = 5;
  1253.           flag   = 1;
  1254.         }
  1255.         else if ( strcasecmp(name,"nsv") == 0 ) {
  1256.           cmpltr = 6;
  1257.           flag   = 1;
  1258.         }
  1259.         else if ( strcasecmp(name,"ev") == 0 ) {
  1260.           cmpltr = 7;
  1261.           flag   = 1;
  1262.         }
  1263.         else
  1264.           as_bad("Unrecognized Add Condition: %s",name);
  1265.         *s = c;
  1266.           }
  1267.           nullif = pa_parse_nullif(&s);
  1268.           opcode |= nullif << 1;
  1269.           opcode |= cmpltr << 13;
  1270.           opcode |= flag << 12;
  1271.           continue;        
  1272.         case '&':   /* logical instruction conditions */
  1273.           cmpltr = 0;
  1274.           f = 0;
  1275.           if ( *s == ',' ) {
  1276.         s++;
  1277.         name = s;
  1278.         while ( *s != ',' && *s != ' ' && *s != '\t' )
  1279.           s += 1;
  1280.         c = *s;
  1281.         *s = 0x00;
  1282.         if ( strcmp(name,"=") == 0 ) {
  1283.           cmpltr = 1;
  1284.         }
  1285.         else if ( strcmp(name,"<") == 0 ) {
  1286.           cmpltr = 2;
  1287.         }
  1288.         else if ( strcmp(name,"<=") == 0 ) {
  1289.           cmpltr = 3;
  1290.         }
  1291.         else if ( strcasecmp(name,"od") == 0 ) {
  1292.           cmpltr = 7;
  1293.         }
  1294.         else if ( strcasecmp(name,"tr") == 0 ) {
  1295.           cmpltr = 0;
  1296.           f = 1;
  1297.         }
  1298.         else if ( strcmp(name,"<>") == 0 ) {
  1299.           cmpltr = 1;
  1300.           f = 1;
  1301.         }
  1302.         else if ( strcmp(name,">=") == 0 ) {
  1303.           cmpltr = 2;
  1304.           f = 1;
  1305.         }
  1306.         else if ( strcmp(name,">") == 0 ) {
  1307.           cmpltr = 3;
  1308.           f = 1;
  1309.         }
  1310.         else if ( strcasecmp(name,"ev") == 0 ) {
  1311.           cmpltr = 7;
  1312.           f = 1;
  1313.         }
  1314.         else
  1315.           as_bad("Unrecognized Logical Instruction Condition: %s",name);
  1316.         *s = c;
  1317.           }
  1318.           opcode |= cmpltr << 13;
  1319.           opcode |= f << 12;        
  1320.           continue;
  1321.         case 'U':   /* unit instruction conditions */
  1322.           cmpltr = 0;
  1323.           f = 0;
  1324.           if ( *s == ',' ) {
  1325.         s++;
  1326.         if ( strncasecmp(s,"sbz",3) == 0 ) {
  1327.           cmpltr = 2;
  1328.           s += 3;
  1329.         }
  1330.         else if ( strncasecmp(s,"shz",3) == 0 ) {
  1331.           cmpltr = 3;
  1332.           s += 3;
  1333.         }
  1334.         else if ( strncasecmp(s,"sdc",3) == 0 ) {
  1335.           cmpltr = 4;
  1336.           s += 3;
  1337.         }
  1338.         else if ( strncasecmp(s,"sbc",3) == 0 ) {
  1339.           cmpltr = 6;
  1340.           s += 3;
  1341.         }
  1342.         else if ( strncasecmp(s,"shc",3) == 0 ) {
  1343.           cmpltr = 7;
  1344.           s += 3;
  1345.         }
  1346.         else if ( strncasecmp(s,"tr",2) == 0 ) {
  1347.           cmpltr = 0;
  1348.           f = 1;
  1349.           s += 2;
  1350.         }
  1351.         else if ( strncasecmp(s,"nbz",3) == 0 ) {
  1352.           cmpltr = 2;
  1353.           f = 1;
  1354.           s += 3;
  1355.         }
  1356.         else if ( strncasecmp(s,"nhz",3) == 0 ) {
  1357.           cmpltr = 3;
  1358.           f = 1;
  1359.           s += 3;
  1360.         }
  1361.         else if ( strncasecmp(s,"ndc",3) == 0 ) {
  1362.           cmpltr = 4;
  1363.           f = 1;
  1364.           s += 3;
  1365.         }
  1366.         else if ( strncasecmp(s,"nbc",3) == 0 ) {
  1367.           cmpltr = 6;
  1368.           f = 1;
  1369.           s += 3;
  1370.         }
  1371.         else if ( strncasecmp(s,"nhc",3) == 0 ) {
  1372.           cmpltr = 7;
  1373.           f = 1;
  1374.           s += 3;
  1375.         }
  1376.         else
  1377.           as_bad("Unrecognized Logical Instruction Condition: %c",*s);
  1378.           }
  1379.           opcode |= cmpltr << 13;
  1380.           opcode |= f << 12;        
  1381.           continue;
  1382.         case '>':   /* shift/extract/deposit conditions. */
  1383.           cmpltr = 0;
  1384.           if ( *s == ',' ) {
  1385.         s++;
  1386.         name = s;
  1387.         while ( *s != ',' && *s != ' ' && *s != '\t' )
  1388.           s += 1;
  1389.         c = *s;
  1390.         *s = 0x00;
  1391.         if ( strcmp(name,"=") == 0 ) {
  1392.           cmpltr = 1;
  1393.         }
  1394.         else if ( strcmp(name,"<") == 0 ) {
  1395.           cmpltr = 2;
  1396.         }
  1397.         else if ( strcasecmp(name,"od") == 0 ) {
  1398.           cmpltr = 3;
  1399.         }
  1400.         else if ( strcasecmp(name,"tr") == 0 ) {
  1401.           cmpltr = 4;
  1402.         }
  1403.         else if ( strcmp(name,"<>") == 0 ) {
  1404.           cmpltr = 5;
  1405.         }
  1406.         else if ( strcmp(name,">=") == 0 ) {
  1407.           cmpltr = 6;
  1408.         }
  1409.         else if ( strcasecmp(name,"ev") == 0 ) {
  1410.           cmpltr = 7;
  1411.         }
  1412.         else
  1413.           as_bad("Unrecognized Shift/Extract/Deposit Condition: %s",name);
  1414.         *s = c;
  1415.           }
  1416.           opcode |= cmpltr << 13;
  1417.           continue;
  1418.         case '~':   /* bvb,bb conditions */
  1419.           cmpltr = 0;
  1420.           if ( *s == ',' ) {
  1421.         s++;
  1422.         if ( strncmp(s,"<",1) == 0 ) {
  1423.           cmpltr = 2;
  1424.           s++;
  1425.         }
  1426.         else if ( strncmp(s,">=",2) == 0 ) {
  1427.           cmpltr = 6;
  1428.           s += 2;
  1429.         }
  1430.         else
  1431.           as_bad("Unrecognized Bit Branch Condition: %c",*s);
  1432.           }
  1433.           opcode |= cmpltr << 13;
  1434.           continue;
  1435.         case 'V':   /* 5  bit immediate at 31 */
  1436.           getExpression(s);
  1437.           low_sign_unext(evaluateAbsolute(the_insn.exp,the_insn.field_selector),
  1438.                  5,&im5);
  1439.           opcode |= im5;
  1440.           s = expr_end;
  1441.           continue;
  1442.         case 'r':   /* 5  bit immediate at 31 */
  1443.           /* (unsigned value for the break instruction) */
  1444.           getExpression(s);
  1445.           im5 = evaluateAbsolute(the_insn.exp,the_insn.field_selector);
  1446.           if ( im5 > 31 || im5 < 0 ) {
  1447.         as_bad("Operand out of range. Was: %d. Should be [0..31]. Assuming %d.\n",im5,im5&0x1f);
  1448.         im5 = im5 & 0x1f;
  1449.           }
  1450.           opcode |= im5;
  1451.           s = expr_end;
  1452.           continue;
  1453.         case 'R':   /* 5  bit immediate at 15 */
  1454.           /* (unsigned value for the ssm and rsm instruction) */
  1455.           getExpression(s);
  1456.           im5 = evaluateAbsolute(the_insn.exp,the_insn.field_selector);
  1457.           if ( im5 > 31 || im5 < 0 ) {
  1458.         as_bad("Operand out of range. Was: %d. Should be [0..31]. Assuming %d.\n",im5,im5&0x1f);
  1459.         im5 = im5 & 0x1f;
  1460.           }
  1461.           opcode |= im5 << 16;
  1462.           s = expr_end;
  1463.           continue;
  1464.         case 'i':   /* 11 bit immediate at 31 */
  1465. #ifdef OBJ_SOM
  1466.           getExpression(s);
  1467.           if ( the_insn.exp.X_seg == &bfd_abs_section ) {
  1468.         low_sign_unext(evaluateAbsolute(the_insn.exp,the_insn.field_selector),
  1469.                    11,&im11);
  1470.         opcode |= im11;
  1471.           }
  1472.           else {
  1473.         the_insn.reloc = R_CODE_ONE_SYMBOL;
  1474.         the_insn.code = 'i';
  1475.         the_insn.field_selector = the_insn.exp.field_selector;
  1476.           }
  1477.           s = expr_end;
  1478.           continue;
  1479. #else
  1480.           the_insn.field_selector = pa_chk_field_selector(&s);
  1481.           getExpression(s);
  1482.           if ( the_insn.exp.X_seg == &bfd_abs_section ) {
  1483.         low_sign_unext(evaluateAbsolute(the_insn.exp,the_insn.field_selector),
  1484.                    11,&im11);
  1485.         opcode |= im11;
  1486.           }
  1487.           else {
  1488.               if ( is_DP_relative(the_insn.exp) )
  1489.                   the_insn.reloc = R_HPPA_GOTOFF;
  1490.               else
  1491.                   the_insn.reloc = R_HPPA;
  1492.               the_insn.format = 11;
  1493.           }
  1494.           s = expr_end;
  1495.           continue;
  1496. #endif
  1497.         case 'j':   /* 14 bit immediate at 31 */
  1498. #ifdef OBJ_SOM
  1499.           getExpression(s);
  1500.           if ( the_insn.exp.X_seg == &bfd_abs_section ) {
  1501.         low_sign_unext(evaluateAbsolute(the_insn.exp,field_selector),
  1502.                    14,&im14);
  1503.         if ( the_insn.exp.field_selector == e_rsel )
  1504.           opcode |= (im14 & 0xfff);
  1505.         else
  1506.           opcode |= im14;
  1507.           }
  1508.           else {
  1509.         the_insn.reloc = R_CODE_ONE_SYMBOL;
  1510.         the_insn.code = 'j';
  1511.         the_insn.field_selector = the_insn.exp.field_selector;
  1512.           }
  1513.           s = expr_end;
  1514.           continue;
  1515. #else
  1516.           the_insn.field_selector = pa_chk_field_selector(&s);
  1517.           getExpression(s);
  1518.           if ( the_insn.exp.X_seg == &bfd_abs_section ) {
  1519.         low_sign_unext(evaluateAbsolute(the_insn.exp,the_insn.field_selector),
  1520.                    14,&im14);
  1521.         if ( the_insn.field_selector == e_rsel )
  1522.           opcode |= (im14 & 0xfff);
  1523.         else
  1524.           opcode |= im14;
  1525.           }
  1526.           else {
  1527.               if ( is_DP_relative(the_insn.exp) )
  1528.                   the_insn.reloc = R_HPPA_GOTOFF;
  1529.               else
  1530.                   the_insn.reloc = R_HPPA;
  1531.               the_insn.format = 14;
  1532.           }
  1533.           s = expr_end;
  1534.           continue;
  1535. #endif
  1536.           
  1537.         case 'k':   /* 21 bit immediate at 31 */
  1538. #ifdef OBJ_SOM
  1539.           getExpression(s);
  1540.           if ( the_insn.exp.X_seg == &bfd_abs_section ) {
  1541.         dis_assemble_21(evaluateAbsolute(the_insn.exp,the_insn.field_selector),
  1542.                 &im21);
  1543.         opcode |= im21;
  1544.           }
  1545.           else {
  1546.         the_insn.reloc = R_CODE_ONE_SYMBOL;
  1547.         the_insn.code = 'k';
  1548.         the_insn.field_selector = the_insn.exp.field_selector;
  1549.           }
  1550.           s = expr_end;
  1551.           continue;
  1552. #else
  1553.           the_insn.field_selector = pa_chk_field_selector(&s);
  1554.           getExpression(s);
  1555.           if ( the_insn.exp.X_seg == &bfd_abs_section ) {
  1556.         dis_assemble_21(evaluateAbsolute(the_insn.exp,the_insn.field_selector),
  1557.                 &im21);
  1558.         opcode |= im21;
  1559.           }
  1560.           else {
  1561.               if ( is_DP_relative(the_insn.exp) )
  1562.                   the_insn.reloc = R_HPPA_GOTOFF;
  1563.               else
  1564.                   the_insn.reloc = R_HPPA;
  1565.               the_insn.format = 21;
  1566.           }
  1567.           s = expr_end;
  1568.           continue;
  1569. #endif
  1570.           
  1571.         case 'n':   /* nullification for branch instructions */
  1572.           nullif = pa_parse_nullif(&s);
  1573.           opcode |= nullif << 1;
  1574.           continue;        
  1575.         case 'w':   /* 12 bit branch displacement */
  1576. #ifdef OBJ_SOM
  1577.           getExpression(s);
  1578.           the_insn.pcrel = 1;
  1579.           if ( strcmp(the_insn.exp.X_add_symbol->sy_nlist.n_un.n_name,"L0\001") == 0 ) {
  1580.         unsigned int w1,w,result;
  1581.         
  1582.         sign_unext( (the_insn.exp.X_add_number - 8) >> 2,12,&result);
  1583.         dis_assemble_12(result,&w1,&w);
  1584.         opcode |= ( ( w1 << 2 ) | w );
  1585.         the_insn.exp.X_add_symbol->sy_ref = FALSE;
  1586.           }
  1587.           else {
  1588.         /* this has to be wrong -- dont know what is right! */
  1589.         the_insn.reloc = R_PCREL_CALL;
  1590.         the_insn.code = 'w';
  1591.         the_insn.field_selector = the_insn.exp.field_selector;
  1592.         the_insn.arg_reloc = last_call_desc.arg_reloc;
  1593.         bzero(&last_call_desc,sizeof(call_descS));
  1594.           }
  1595.           s = expr_end;
  1596.           continue;
  1597. #else
  1598.           the_insn.field_selector = pa_chk_field_selector(&s);
  1599.           getExpression(s);
  1600.           the_insn.pcrel = 1;
  1601.           if ( strcmp(S_GET_NAME(the_insn.exp.X_add_symbol),"L0\001") == 0 ) {
  1602.         unsigned int w1,w,result;
  1603.         
  1604.         sign_unext( (the_insn.exp.X_add_number - 8) >> 2,12,&result);
  1605.         dis_assemble_12(result,&w1,&w);
  1606.         opcode |= ( ( w1 << 2 ) | w );
  1607.         /* the_insn.exp.X_add_symbol->sy_ref = FALSE; */ /* XXX: not sure how to do this in BFD */
  1608.           }
  1609.           else {
  1610.               /* this has to be wrong -- dont know what is right! */
  1611.               the_insn.reloc = R_HPPA_PCREL_CALL;
  1612.         the_insn.format = 12;
  1613.         the_insn.arg_reloc = last_call_desc.arg_reloc;
  1614.         bzero(&last_call_desc,sizeof(call_descS));
  1615.           }
  1616.           s = expr_end;
  1617.           continue;
  1618. #endif
  1619.         case 'W':   /* 17 bit branch displacement */
  1620. #if defined(OBJ_ELF)
  1621.           the_insn.field_selector = pa_chk_field_selector(&s);
  1622. #endif
  1623.           getExpression(s);
  1624.           the_insn.pcrel = 1;
  1625. #ifdef OBJ_SOM
  1626.           if ( strcmp(the_insn.exp.X_add_symbol->sy_nlist.n_un.n_name,"L0\001") == 0 ) {
  1627.         unsigned int w2,w1,w,result;
  1628.  
  1629.         sign_unext( (the_insn.exp.X_add_number - 8) >> 2,17,&result);
  1630.         dis_assemble_17(result,&w1,&w2,&w);
  1631.         opcode |= ( ( w2 << 2 ) | ( w1 << 16 ) | w );
  1632.         the_insn.exp.X_add_symbol->sy_ref = FALSE;
  1633.           }
  1634.           else {
  1635.         /* this has to be wrong -- dont know what is right! */
  1636.         the_insn.reloc = R_PCREL_CALL;
  1637.         the_insn.code = 'W';
  1638.         the_insn.field_selector = the_insn.exp.field_selector;
  1639.         the_insn.arg_reloc = last_call_desc.arg_reloc;
  1640.         bzero(&last_call_desc,sizeof(call_descS));
  1641.           }
  1642. #else
  1643.           if ( the_insn.exp.X_add_symbol ) {
  1644.               if ( strcmp(S_GET_NAME(the_insn.exp.X_add_symbol),"L0\001") == 0 ) {
  1645.                   unsigned int w2,w1,w,result;
  1646.  
  1647.                   sign_unext( (the_insn.exp.X_add_number - 8) >> 2,17,&result);
  1648.                   dis_assemble_17(result,&w1,&w2,&w);
  1649.                   opcode |= ( ( w2 << 2 ) | ( w1 << 16 ) | w );
  1650.               }
  1651.               else {
  1652.                   /* this has to be wrong -- dont know what is right! */
  1653.                   the_insn.reloc = R_HPPA_PCREL_CALL;
  1654.                   the_insn.format = 17;
  1655.                   the_insn.arg_reloc = last_call_desc.arg_reloc;
  1656.                   bzero(&last_call_desc,sizeof(call_descS));
  1657.               }
  1658.           }
  1659.           else {
  1660.               unsigned int w2,w1,w,result;
  1661.  
  1662.               sign_unext( the_insn.exp.X_add_number >> 2,17,&result);
  1663.               dis_assemble_17(result,&w1,&w2,&w);
  1664.               opcode |= ( ( w2 << 2 ) | ( w1 << 16 ) | w );
  1665.           }              
  1666. #endif
  1667.           s = expr_end;
  1668.           continue;
  1669.         case 'p':   /* 5 bit shift count at 26 (to support SHD instr.) */
  1670.           /* value is encoded in instr. as 31-p where p is   */
  1671.           /* the value scanned here */
  1672.           getExpression(s);
  1673.           if ( the_insn.exp.X_seg == &bfd_abs_section ) {
  1674.         opcode |= ( ( (31 - the_insn.exp.X_add_number) & 0x1f ) << 5 );
  1675.           }
  1676.           s = expr_end;
  1677.           continue;
  1678.         case 'P':   /* 5-bit bit position at 26 */
  1679.           getExpression(s);
  1680.           if ( the_insn.exp.X_seg == &bfd_abs_section ) {
  1681.         opcode |= ( the_insn.exp.X_add_number & 0x1f ) << 5;
  1682.           }
  1683.           s = expr_end;
  1684.           continue;
  1685.         case 'Q':   /* 5  bit immediate at 10 */
  1686.           /* (unsigned bit position value for the bb instruction) */
  1687.           getExpression(s);
  1688.           im5 = evaluateAbsolute(the_insn.exp,the_insn.field_selector);
  1689.           if ( im5 > 31 || im5 < 0 ) {
  1690.         as_bad("Operand out of range. Was: %d. Should be [0..31]. Assuming %d.\n",im5,im5&0x1f);
  1691.         im5 = im5 & 0x1f;
  1692.           }
  1693.           opcode |= im5 << 21;
  1694.           s = expr_end;
  1695.           continue;
  1696.         case 'A':   /* 13 bit immediate at 18 (to support BREAK instr.) */
  1697.           getAbsoluteExpression(s);
  1698.           if ( the_insn.exp.X_seg == &bfd_abs_section )
  1699.         opcode |= (the_insn.exp.X_add_number & 0x1fff) << 13;
  1700.           s = expr_end;
  1701.           continue;
  1702.         case 'Z':   /* System Control Completer(for LDA, LHA, etc.) */
  1703.           if ( *s == ',' && ( *(s+1) == 'm' || *(s+1) == 'M' ) ) {
  1704.         m = 1;
  1705.         s += 2;
  1706.           }
  1707.           else
  1708.         m = 0;
  1709.           
  1710.           opcode |= m << 5;
  1711.           while ( *s == ' ' || *s == '\t' ) /* skip to next operand */
  1712.         s++;
  1713.           
  1714.           continue;
  1715.         case 'D':   /* 26 bit immediate at 31 (to support DIAG instr.) */
  1716.           /* the action (and interpretation of this operand is
  1717.                  implementation dependent) */
  1718. #if defined(OBJ_ELF)
  1719.           the_insn.field_selector = pa_chk_field_selector(&s);
  1720. #endif
  1721.           getExpression(s);
  1722.           if ( the_insn.exp.X_seg == &bfd_abs_section ) {
  1723.         opcode |= ( (evaluateAbsolute(the_insn.exp,the_insn.field_selector) & 0x1ffffff) << 1 );
  1724. #ifdef NEW_SOM /* XXX what replaces this? */
  1725.               /* PJH: VERY unsure about the following */
  1726.         the_insn.field_selector = the_insn.exp.field_selector;
  1727. #endif
  1728.           }
  1729.           else
  1730.         as_bad("Illegal DIAG operand");
  1731.           s = expr_end;
  1732.           continue;
  1733.         case 'f':   /* 3 bit Special Function Unit (SFU) identifier at 25 */
  1734.           sfu = pa_parse_number(&s);
  1735.           if ( (sfu > 7) || (sfu < 0) )
  1736.         as_bad("Illegal SFU identifier: %02x", sfu);
  1737.           opcode |= (sfu & 7) << 6;
  1738.           continue;
  1739.         case 'O':   /* 20 bit SFU op. split between 15 bits at 20
  1740.                        and 5 bits at 31 */
  1741.           getExpression(s);
  1742.           s = expr_end;
  1743.           continue;
  1744.         case 'o':   /* 15 bit Special Function Unit operation at 20 */
  1745.           getExpression(s);
  1746.           s = expr_end;
  1747.           continue;
  1748.         case '2':   /* 22 bit SFU op. split between 17 bits at 20
  1749.                        and 5 bits at 31 */
  1750.           getExpression(s);
  1751.           s = expr_end;
  1752.           continue;
  1753.         case '1':   /* 15 bit SFU op. split between 10 bits at 20
  1754.                        and 5 bits at 31 */
  1755.           getExpression(s);
  1756.           s = expr_end;
  1757.           continue;
  1758.         case '0':   /* 10 bit SFU op. split between 5 bits at 20
  1759.                        and 5 bits at 31 */
  1760.           getExpression(s);
  1761.           s = expr_end;
  1762.           continue;
  1763.         case 'u':   /* 3 bit coprocessor unit identifier at 25 */
  1764.           getExpression(s);
  1765.           s = expr_end;
  1766.           continue;
  1767.         case 'F':   /* Source FP Operand Format Completer (2 bits at 20) */
  1768.           f = pa_parse_fp_format(&s);
  1769.           opcode |= (int)f << 11;
  1770.           the_insn.fpof1 = f;
  1771.           continue;
  1772.         case 'G':   /* Destination FP Operand Format Completer (2 bits at 18) */
  1773.           s--;      /* need to pass the previous comma to pa_parse_fp_format */
  1774.           f = pa_parse_fp_format(&s);
  1775.           opcode |= (int)f << 13;
  1776.           the_insn.fpof2 = f;
  1777.           continue;
  1778.         case 'M':   /* FP Compare Conditions (encoded as 5 bits at 31) */
  1779.           cond = pa_parse_fp_cmp_cond(&s);
  1780.           opcode |= cond;
  1781.           continue;
  1782.  
  1783.             case 'v':   /* a 't' type extended to handle L/R register halves. */
  1784.           {
  1785.         struct pa_89_fp_reg_struct result;
  1786.         int status;
  1787.  
  1788.         pa_89_parse_number(&s,&result);
  1789.         if ( result.number_part < 32 && result.number_part >= 0 ) {
  1790.           opcode |= (result.number_part & 0x1f);
  1791.  
  1792.           /* 0x30 opcodes are FP arithmetic operation opcodes */
  1793.           /* load/store FP opcodes do not get converted to 0x38 */
  1794.                   /* opcodes like the 0x30 opcodes do */
  1795.           if ( need_89_opcode(&the_insn,&result) ) {
  1796.             if ( (opcode & 0xfc000000) == 0x30000000 ) {
  1797.               opcode |= (result.L_R_select & 1) << 6;
  1798.               opcode |= 1 << 27;
  1799.             }
  1800.             else {
  1801.               opcode |= (result.L_R_select & 1) << 6;
  1802.             }
  1803.           }
  1804.           continue;
  1805.         }
  1806.           }
  1807.           break;
  1808.         case 'E':   /* a 'b' type extended to handle L/R register halves. */
  1809.           {
  1810.         struct pa_89_fp_reg_struct result;
  1811.         int status;
  1812.  
  1813.         pa_89_parse_number(&s,&result);
  1814.         if ( result.number_part < 32 && result.number_part >= 0 ) {
  1815.           opcode |= (result.number_part & 0x1f) << 21;
  1816.           if ( need_89_opcode(&the_insn,&result) ) {
  1817.             opcode |= (result.L_R_select & 1) << 7;
  1818.             opcode |= 1 << 27;
  1819.           }
  1820.           continue;
  1821.         }
  1822.           }
  1823.           break;
  1824.  
  1825.         case 'X':   /* an 'x' type extended to handle L/R register halves. */
  1826.           {
  1827.         struct pa_89_fp_reg_struct result;
  1828.         int status;
  1829.  
  1830.  
  1831.         pa_89_parse_number(&s,&result);
  1832.         if ( result.number_part < 32 && result.number_part >= 0 ) {
  1833.           opcode |= (result.number_part & 0x1f) << 16;
  1834.           if ( need_89_opcode(&the_insn,&result) ) {
  1835.             opcode |= (result.L_R_select & 1) << 12;
  1836.             opcode |= 1 << 27;
  1837.           }
  1838.           continue;
  1839.         }
  1840.           }
  1841.           break;
  1842.  
  1843.         case '4':   /* 5 bit register field at 10
  1844.                  (used in 'fmpyadd' and 'fmpysub') */
  1845.           {
  1846.         struct pa_89_fp_reg_struct result;
  1847.         int status;
  1848.  
  1849.         status = pa_89_parse_number(&s,&result);
  1850.         if ( result.number_part < 32 && result.number_part >= 0 ) {
  1851.           if ( the_insn.fpof1 == SGL ) {
  1852.             result.number_part &= 0xF;
  1853.             result.number_part |= (result.L_R_select & 1) << 4;
  1854.           }
  1855.           opcode |= result.number_part << 21;
  1856.           continue;
  1857.         }
  1858.           }
  1859.           break;
  1860.  
  1861.         case '6':   /* 5 bit register field at 15
  1862.                  (used in 'fmpyadd' and 'fmpysub') */
  1863.           {
  1864.         struct pa_89_fp_reg_struct result;
  1865.         int status;
  1866.  
  1867.         status = pa_89_parse_number(&s,&result);
  1868.         if ( result.number_part < 32 && result.number_part >= 0 ) {
  1869.           if ( the_insn.fpof1 == SGL ) {
  1870.             result.number_part &= 0xF;
  1871.             result.number_part |= (result.L_R_select & 1) << 4;
  1872.           }
  1873.           opcode |= result.number_part << 16;
  1874.           continue;
  1875.         }
  1876.           }
  1877.           break;
  1878.  
  1879.         case '7':   /* 5 bit register field at 31
  1880.                  (used in 'fmpyadd' and 'fmpysub') */
  1881.           {
  1882.         struct pa_89_fp_reg_struct result;
  1883.         int status;
  1884.  
  1885.         status = pa_89_parse_number(&s,&result);
  1886.         if ( result.number_part < 32 && result.number_part >= 0 ) {
  1887.           if ( the_insn.fpof1 == SGL ) {
  1888.             result.number_part &= 0xF;
  1889.             result.number_part |= (result.L_R_select & 1) << 4;
  1890.           }
  1891.           opcode |= result.number_part;
  1892.           continue;
  1893.         }
  1894.           }
  1895.           break;
  1896.  
  1897.         case '8':   /* 5 bit register field at 20
  1898.                  (used in 'fmpyadd' and 'fmpysub') */
  1899.           {
  1900.         struct pa_89_fp_reg_struct result;
  1901.         int status;
  1902.  
  1903.         status = pa_89_parse_number(&s,&result);
  1904.         if ( result.number_part < 32 && result.number_part >= 0 ) {
  1905.           if ( the_insn.fpof1 == SGL ) {
  1906.             result.number_part &= 0xF;
  1907.             result.number_part |= (result.L_R_select & 1) << 4;
  1908.           }
  1909.           opcode |= result.number_part << 11;
  1910.           continue;
  1911.         }
  1912.           }
  1913.           break;
  1914.  
  1915.         case '9':   /* 5 bit register field at 25
  1916.                  (used in 'fmpyadd' and 'fmpysub') */
  1917.           {
  1918.         struct pa_89_fp_reg_struct result;
  1919.         int status;
  1920.  
  1921.         status = pa_89_parse_number(&s,&result);
  1922.         if ( result.number_part < 32 && result.number_part >= 0 ) {
  1923.           if ( the_insn.fpof1 == SGL ) {
  1924.             result.number_part &= 0xF;
  1925.             result.number_part |= (result.L_R_select & 1) << 4;
  1926.           }
  1927.           opcode |= result.number_part << 6;
  1928.           continue;
  1929.         }
  1930.           }
  1931.           break;
  1932.  
  1933.         case 'H':  /* Floating Point Operand Format at 26 for       */
  1934.                    /* 'fmpyadd' and 'fmpysub' (very similar to 'F') */
  1935.                    /* bits are switched from other FP Operand       */
  1936.                    /* formats. 1=SGL, 1=<none>, 0=DBL               */
  1937.           f = pa_parse_fp_format(&s);
  1938.           switch (f) {
  1939.           case SGL:
  1940.         opcode |= 0x20;
  1941.           case DBL:
  1942.         the_insn.fpof1 = f;
  1943.         continue;
  1944.  
  1945.           case QUAD:
  1946.           case ILLEGAL_FMT:
  1947.           default:
  1948.         as_bad("Illegal Floating Point Operand Format for this instruction: '%s'",*s);
  1949.           }
  1950.           break;
  1951.  
  1952.         default:
  1953.         abort();
  1954.         }
  1955.         break;
  1956.       }
  1957.     error:
  1958.     if (match == FALSE)
  1959.       {
  1960.         /* Args don't match.  */
  1961.         if (&insn[1] - pa_opcodes < NUMOPCODES
  1962.         && !strcmp(insn->name, insn[1].name))
  1963.           {
  1964.         ++insn;
  1965.         s = argsStart;
  1966.         continue;
  1967.           }
  1968.         else
  1969.               {
  1970.         as_bad("Illegal operands %s",error_message );
  1971.         return;
  1972.               }
  1973.       }
  1974.     break;
  1975.     }
  1976.  
  1977.     the_insn.opcode = opcode;
  1978.  
  1979. #ifdef PA_DEBUG
  1980.     if ( the_insn.exp.X_add_symbol && the_insn.exp.X_subtract_symbol )
  1981.        print_insn_short(&the_insn);
  1982.     fprintf(stderr,"*********** END OF STATEMENT\n");
  1983. #endif
  1984.  
  1985.     return;
  1986. }
  1987.  
  1988. /*
  1989.     This is identical to the md_atof in m68k.c.  I think this is right,
  1990.     but I'm not sure.
  1991.  
  1992.    Turn a string in input_line_pointer into a floating point constant of type
  1993.    type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
  1994.    emitted is stored in *sizeP .  An error message is returned, or NULL on OK.
  1995.  */
  1996.  
  1997. /* Equal to MAX_PRECISION in atof-ieee.c */
  1998. #define MAX_LITTLENUMS 6
  1999.  
  2000. char *
  2001. md_atof(type,litP,sizeP)
  2002.     char type;
  2003.     char *litP;
  2004.     int *sizeP;
  2005. {
  2006.     int    prec;
  2007.     LITTLENUM_TYPE words[MAX_LITTLENUMS];
  2008.     LITTLENUM_TYPE *wordP;
  2009.     char    *t;
  2010.     char    *atof_ieee();
  2011.  
  2012.     switch(type) {
  2013.  
  2014.     case 'f':
  2015.     case 'F':
  2016.     case 's':
  2017.     case 'S':
  2018.     prec = 2;
  2019.     break;
  2020.  
  2021.     case 'd':
  2022.     case 'D':
  2023.     case 'r':
  2024.     case 'R':
  2025.     prec = 4;
  2026.     break;
  2027.  
  2028.     case 'x':
  2029.     case 'X':
  2030.     prec = 6;
  2031.     break;
  2032.  
  2033.     case 'p':
  2034.     case 'P':
  2035.     prec = 6;
  2036.     break;
  2037.  
  2038.     default:
  2039.     *sizeP=0;
  2040.     return "Bad call to MD_ATOF()";
  2041.     }
  2042.     t=atof_ieee(input_line_pointer,type,words);
  2043.     if(t)
  2044.     input_line_pointer=t;
  2045.     *sizeP=prec * sizeof(LITTLENUM_TYPE);
  2046.     for(wordP=words;prec--;) {
  2047.     md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
  2048.     litP+=sizeof(LITTLENUM_TYPE);
  2049.     }
  2050.     return "";    /* Someone should teach Dean about null pointers */
  2051. }
  2052.  
  2053. /*
  2054.  * Write out big-endian.
  2055.  */
  2056. void
  2057. md_number_to_chars(buf,val,n)
  2058.     char *buf;
  2059.     long val;
  2060.     int n;
  2061. {
  2062.  
  2063.     switch(n) {
  2064.  
  2065.     case 4:
  2066.     *buf++ = val >> 24;
  2067.     *buf++ = val >> 16;
  2068.     case 2:
  2069.     *buf++ = val >> 8;
  2070.     case 1:
  2071.     *buf = val;
  2072.     break;
  2073.  
  2074.     default:
  2075.     abort();
  2076.     }
  2077.     return;
  2078. }
  2079.  
  2080. void
  2081. md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)
  2082.     char *ptr;
  2083.     long from_addr, to_addr;
  2084.     fragS *frag;
  2085.     symbolS *to_symbol;
  2086. {
  2087.     fprintf(stderr, "pa_create_short_jmp\n");
  2088.     abort();
  2089. }
  2090.  
  2091. void
  2092. md_number_to_disp(buf,val,n)
  2093.     char    *buf;
  2094.     long    val;
  2095.     int        n;
  2096. {
  2097.     fprintf(stderr, "md_number_to_disp\n");
  2098.     abort();
  2099. }
  2100.  
  2101. void
  2102. md_number_to_field(buf,val,fix)
  2103.     char *buf;
  2104.     long val;
  2105.     void *fix;
  2106. {
  2107.     fprintf(stderr, "pa_number_to_field\n");
  2108.     abort();
  2109. }
  2110.  
  2111. /* the bit-field entries in the relocation_info struct plays hell 
  2112.    with the byte-order problems of cross-assembly.  So as a hack,
  2113.    I added this mach. dependent ri twiddler.  Ugly, but it gets
  2114.    you there. -KWK */
  2115. /* on sparc: first 4 bytes are normal unsigned long address, next three
  2116.    bytes are index, most sig. byte first.  Byte 7 is broken up with
  2117.    bit 7 as external, bits 6 & 5 unused, and the lower
  2118.    five bits as relocation type.  Next 4 bytes are long int addend. */
  2119. /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
  2120.  
  2121. #ifdef OBJ_SOM
  2122. void
  2123. md_ri_to_chars(ri_p, ri)
  2124.      struct reloc_info_pa *ri_p, ri;
  2125. {
  2126.   unsigned char the_bytes[sizeof(*ri_p)];
  2127. #if defined(OBJ_SOM) | defined(OBJ_OSFROSE) | defined(OBJ_ELF)
  2128.   /* not sure what, if any, changes are required for new-style cross-assembly */
  2129. #else
  2130.   the_bytes[0] = ((ri.need_data_ref << 7) & 0x80) | ((ri.arg_reloc & 0x03f8) >> 3);
  2131.   the_bytes[1] = ((ri.arg_reloc & 0x07) << 5) | ri.expression_type;
  2132.   the_bytes[2] = ((ri.exec_level << 6) & 0xc0) | ri.fixup_format;
  2133.   the_bytes[3] = ri.fixup_field & 0xff;
  2134.   md_number_to_chars(&the_bytes[4], ri.subspace_offset, sizeof(ri.subspace_offset));
  2135.   md_number_to_chars(&the_bytes[8], ri.symbol_index_one, sizeof(ri.symbol_index_one));
  2136.   md_number_to_chars(&the_bytes[12], ri.symbol_index_two, sizeof(ri.symbol_index_two));
  2137.   md_number_to_chars(&the_bytes[16], ri.fixup_constant, sizeof(ri.fixup_constant));
  2138.  
  2139.   /* now put it back where you found it, Junior... */
  2140.   bcopy (the_bytes, (char *)ri_p, sizeof(*ri_p));
  2141. #endif
  2142.  
  2143. }
  2144. #endif
  2145.  
  2146.  
  2147. /* Translate internal representation of relocation info to BFD target
  2148.    format.  */
  2149.  
  2150. arelent * tc_gen_reloc (section, fixp)
  2151. asection * section;
  2152. fixS * fixp;
  2153. {
  2154.     arelent *reloc;
  2155.     hppa_fixS *hppa_fixp = hppa_find_hppa_fix(fixp);
  2156.     bfd_reloc_code_real_type code;
  2157.     static int unwind_reloc_fixp_cnt = 0;
  2158.     static arelent *unwind_reloc_entryP = NULL;
  2159.  
  2160.     if ( fixp->fx_addsy == 0 )
  2161.         return 0;
  2162.     assert (hppa_fixp != 0);
  2163.     assert (section != 0);
  2164.  
  2165.     /* unwind section relocations are handled in a special way. */
  2166.     /* The relocations for the .unwind section are originally */
  2167.     /* built in the usual way.  That is, for each unwind table */
  2168.     /* entry there are two relocations:  one for the beginning of */
  2169.     /* the function and one for the end.    */
  2170.  
  2171.     /* The first time we enter this function we create a */
  2172.     /* relocation of the type R_HPPA_UNWIND_ENTRIES.  The addend */
  2173.     /* of the relocation is initialized to 0.  Each additional */
  2174.     /* pair of times this function is called for the unwind */
  2175.     /* section represents an additional unwind table entry.  Thus, */
  2176.     /* the addend of the relocation should end up to be the number */
  2177.     /* of unwind table entries. */
  2178.     if ( strcmp(UNWIND_SECTION_NAME,section->name) == 0 ) {
  2179.         if ( unwind_reloc_entryP == NULL ) {
  2180.             reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
  2181.             assert (reloc != 0);
  2182.             unwind_reloc_entryP = reloc;
  2183.             unwind_reloc_fixp_cnt++;
  2184.             unwind_reloc_entryP->address = fixp->fx_frag->fr_address + fixp->fx_where;
  2185.             /* a pointer any function will do.  We only */
  2186.             /* need one to tell us what section the unwind */
  2187.             /* relocations are for. */
  2188.             unwind_reloc_entryP->sym_ptr_ptr = &fixp->fx_addsy->bsym;
  2189.             code = R_HPPA_UNWIND_ENTRIES;
  2190.             unwind_reloc_entryP->howto = bfd_reloc_type_lookup (stdoutput, code);
  2191.             unwind_reloc_entryP->addend = unwind_reloc_fixp_cnt / 2;
  2192.  
  2193.             return unwind_reloc_entryP;
  2194.         }
  2195.         unwind_reloc_fixp_cnt++;
  2196.         unwind_reloc_entryP->addend = unwind_reloc_fixp_cnt / 2;
  2197.  
  2198.         return NULL;        
  2199.     }
  2200.  
  2201.     reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
  2202.     assert (reloc != 0);
  2203.  
  2204.     reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
  2205.     /* XXX: might need additional processing here    */
  2206.     /* hppa_elf_gen_reloc_type() is defined in the    */
  2207.     /* ELF/PA BFD back-end                */
  2208.     code = hppa_elf_gen_reloc_type(fixp->fx_r_type,
  2209.                        hppa_fixp->fx_r_format,
  2210.                        hppa_fixp->fx_r_field);
  2211.     reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
  2212.  
  2213.     assert(code == reloc->howto->type);
  2214.  
  2215.     reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
  2216.     reloc->addend = 0;    /* default */
  2217.  
  2218.     /* Now, do any processing that is dependent on the relocation */
  2219.     /* type. */
  2220.     switch ( code ) {
  2221.         case R_HPPA_PLABEL_32:
  2222.         case R_HPPA_PLABEL_11:
  2223.         case R_HPPA_PLABEL_14:
  2224.         case R_HPPA_PLABEL_L21:
  2225.         case R_HPPA_PLABEL_R11:
  2226.         case R_HPPA_PLABEL_R14:
  2227.         /* For plabel relocations, the addend of the */
  2228.         /* relocation should be either 0 (no static link) or 2 */
  2229.         /* (static link required).    */
  2230.         /* XXX: assume that fx_addnumber contains this */
  2231.         /* information */
  2232.         reloc->addend = fixp->fx_addnumber;
  2233.         break;
  2234.  
  2235.         case R_HPPA_ABS_CALL_11:
  2236.         case R_HPPA_ABS_CALL_14:
  2237.         case R_HPPA_ABS_CALL_17:
  2238.         case R_HPPA_ABS_CALL_L21:
  2239.         case R_HPPA_ABS_CALL_R11:
  2240.         case R_HPPA_ABS_CALL_R14:
  2241.         case R_HPPA_ABS_CALL_R17:
  2242.         case R_HPPA_ABS_CALL_LS21:
  2243.         case R_HPPA_ABS_CALL_RS11:
  2244.         case R_HPPA_ABS_CALL_RS14:
  2245.         case R_HPPA_ABS_CALL_RS17:
  2246.         case R_HPPA_ABS_CALL_LD21:
  2247.         case R_HPPA_ABS_CALL_RD11:
  2248.         case R_HPPA_ABS_CALL_RD14:
  2249.         case R_HPPA_ABS_CALL_RD17:
  2250.         case R_HPPA_ABS_CALL_LR21:
  2251.         case R_HPPA_ABS_CALL_RR14:
  2252.         case R_HPPA_ABS_CALL_RR17:
  2253.         
  2254.         case R_HPPA_PCREL_CALL_11:
  2255.         case R_HPPA_PCREL_CALL_14:
  2256.         case R_HPPA_PCREL_CALL_17:
  2257.         case R_HPPA_PCREL_CALL_L21:
  2258.         case R_HPPA_PCREL_CALL_R11:
  2259.         case R_HPPA_PCREL_CALL_R14:
  2260.         case R_HPPA_PCREL_CALL_R17:
  2261.         case R_HPPA_PCREL_CALL_LS21:
  2262.         case R_HPPA_PCREL_CALL_RS11:
  2263.         case R_HPPA_PCREL_CALL_RS14:
  2264.         case R_HPPA_PCREL_CALL_RS17:
  2265.         case R_HPPA_PCREL_CALL_LD21:
  2266.         case R_HPPA_PCREL_CALL_RD11:
  2267.         case R_HPPA_PCREL_CALL_RD14:
  2268.         case R_HPPA_PCREL_CALL_RD17:
  2269.         case R_HPPA_PCREL_CALL_LR21:
  2270.         case R_HPPA_PCREL_CALL_RR14:
  2271.         case R_HPPA_PCREL_CALL_RR17:
  2272.         /* constant is stored in the instruction */
  2273.         reloc->addend = ELF32_HPPA_R_ADDEND(hppa_fixp->fx_arg_reloc,0);
  2274.         break;
  2275.         default:
  2276.         reloc->addend = fixp->fx_addnumber;
  2277.         break;
  2278.     }
  2279.  
  2280.     return reloc;
  2281. }
  2282.  
  2283. void
  2284. md_convert_frag(abfd, sec, fragP)
  2285.     register bfd *abfd;
  2286.     register asection *sec;
  2287.     register fragS *fragP;
  2288. {
  2289.   unsigned int address;
  2290.  
  2291.   if ( fragP -> fr_type == rs_machine_dependent ) {
  2292.     switch ( (int) fragP -> fr_subtype ) {
  2293.     case 0:
  2294.       fragP -> fr_type = rs_fill;
  2295.       know( fragP -> fr_var == 1 );
  2296.       know( fragP -> fr_next );
  2297.       address = fragP -> fr_address + fragP -> fr_fix;
  2298.       if ( address % fragP -> fr_offset ) {
  2299.     fragP -> fr_offset =
  2300.       fragP -> fr_next -> fr_address
  2301.         -   fragP -> fr_address
  2302.           - fragP -> fr_fix;
  2303.       }
  2304.       else
  2305.     fragP -> fr_offset = 0;
  2306.       break;
  2307.     }
  2308.   }
  2309. }
  2310.  
  2311. /* Round up a section size to the appropriate boundary. */
  2312. long
  2313. md_section_align (segment, size)
  2314.      asection *segment;
  2315.      long size;
  2316. {
  2317.   return (size + 7) & ~7;    /* Round all sects to multiple of 8 */
  2318. } /* md_section_align() */
  2319.  
  2320. void
  2321. md_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol)
  2322.     char    *ptr;
  2323.     long    from_addr,
  2324.             to_addr;
  2325.     fragS    *frag;
  2326.     symbolS    *to_symbol;
  2327. {
  2328.     fprintf(stderr, "pa_create_long_jump\n");
  2329.     abort();
  2330. }
  2331.  
  2332. int
  2333. /* md_estimate_size_before_relax(fragP, segtype) */
  2334. md_estimate_size_before_relax(fragP, segment)
  2335.     register fragS *fragP;
  2336.     asection *segment;
  2337. {
  2338.   int size;
  2339.  
  2340.   size = 0;
  2341.  
  2342.   while ( (fragP->fr_fix + size) % fragP->fr_offset )
  2343.     size++;
  2344.  
  2345.   return size;
  2346. }
  2347.  
  2348. int
  2349. md_parse_option(argP,cntP,vecP)
  2350.     char **argP;
  2351.     int *cntP;
  2352.     char ***vecP;
  2353. {
  2354.     return 1;
  2355. }
  2356.  
  2357. /* We have no need to default values of symbols. */
  2358.  
  2359. /* ARGSUSED */
  2360. symbolS *md_undefined_symbol(name)
  2361. char *name;
  2362. {
  2363.         return 0;
  2364. } /*md_undefined_symbol() */
  2365.  
  2366. /* Parse an operand that is machine-specific.
  2367.    We just return without modifying the expression if we have nothing
  2368.    to do.  */
  2369.  
  2370. /* ARGSUSED */
  2371. void
  2372. md_operand (expressionP)
  2373.      expressionS *expressionP;
  2374. {
  2375. }
  2376.  
  2377. /* Apply a fixS to the frags, now that we know the value it ought to
  2378.    hold. */
  2379.  
  2380. int apply_field_selector(value,constant,field_selector)
  2381. long value;
  2382. long constant;
  2383. int field_selector;
  2384. {
  2385.     /* hppa_field_adjust() is defined in the HPPA target */
  2386.     return hppa_field_adjust(value,constant,field_selector);
  2387. }
  2388.  
  2389. void md_apply_fix(fixP, val)
  2390. fixS *fixP;
  2391. long val;
  2392. {
  2393.     char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
  2394.     hppa_fixS *hppa_fixP = hppa_find_hppa_fix(fixP);
  2395.     long new_val;
  2396.     long result;
  2397.     unsigned int w1,w2,w;
  2398.     /* The following routine is defined in the ELF/PA back-end    */
  2399.     extern unsigned char hppa_elf_insn2fmt();
  2400.  
  2401.     if ( hppa_fixP ) {
  2402.         unsigned char fmt = hppa_elf_insn2fmt(fixP->fx_r_type,
  2403.                               *(unsigned long *)buf);
  2404.  
  2405.         assert(fixP->fx_r_type < R_HPPA_UNIMPLEMENTED);
  2406.         assert(fixP->fx_r_type >= R_HPPA_NONE);
  2407.  
  2408.         fixP->fx_addnumber = val;    /* Remember value for emit_reloc */
  2409.  
  2410.         /* Check if this is an undefined symbol.  No relocation can    */
  2411.         /* possibly be performed in this case.                */
  2412.  
  2413.         if ( (fixP->fx_addsy && fixP->fx_addsy->bsym->section == &bfd_und_section)
  2414.             || (fixP->fx_subsy && fixP->fx_subsy->bsym->section == &bfd_und_section) )
  2415.             return;
  2416.  
  2417.         /* Perform some processing particular to unwind */
  2418.         /* relocations */
  2419.  
  2420.         if ( hppa_fixP->fx_call_infop
  2421.             && ( ( (fixP == hppa_fixP->fx_call_infop->start_fix)
  2422.               && (fixP->fx_addsy ==
  2423.                   hppa_fixP->fx_call_infop->start_symbol) )
  2424.             || ( (fixP == hppa_fixP->fx_call_infop->end_fix)
  2425.                 && (fixP->fx_addsy ==
  2426.                   hppa_fixP->fx_call_infop->end_symbol) )
  2427.             ) )
  2428.             val += fixP->fx_addsy->sy_frag->fr_address;
  2429.  
  2430.         switch (fmt) {
  2431.             
  2432.             case 14:    /* all the opcodes with the 'j' operand type */
  2433.             new_val = apply_field_selector(val,0,hppa_fixP->fx_r_field);
  2434.             /* need to check for overflow here */
  2435.             
  2436.             /* mask off 14 bits to be changed */
  2437.             *(long *)buf = *(long *)buf & 0xffffc000;
  2438.             low_sign_unext(new_val,14,&result);
  2439.             break;
  2440.             
  2441.             case 21:    /* all the opcodes with the 'k' operand type */
  2442.             new_val = apply_field_selector(val,0,hppa_fixP->fx_r_field);
  2443.             /* need to check for overflow here */
  2444.             
  2445.             /* mask off 21 bits to be changed */
  2446.             *(long *)buf = *(long *)buf & 0xffe00000;
  2447.             dis_assemble_21(new_val,&result);
  2448.             break;
  2449.             
  2450.             case 11:    /* all the opcodes with the 'i' operand type */
  2451.             new_val = apply_field_selector(val,0,hppa_fixP->fx_r_field);
  2452.             /* need to check for overflow here */
  2453.             
  2454.             /* mask off 11 bits to be changed */
  2455.             *(long *)buf = *(long *)buf & 0xffff800;
  2456.             low_sign_unext(new_val,11,&result);
  2457.             break;
  2458.             
  2459.             case 12:    /* all the opcodes with the 'w' operand type */
  2460.             new_val = apply_field_selector(val,0,hppa_fixP->fx_r_field);
  2461.             
  2462.             /* mask off 11 bits to be changed */
  2463.             sign_unext( (new_val - 8) >> 2,12,&result);
  2464.             *(long *)buf = *(long *)buf & 0xffffe002;
  2465.             
  2466.             dis_assemble_12(result,&w1,&w);
  2467.             result = ( ( w1 << 2 ) | w );
  2468.             break;
  2469.             
  2470.             case 17:    /* some of the opcodes with the 'W' operand type */
  2471.             new_val = apply_field_selector(val,0,hppa_fixP->fx_r_field);
  2472.             /* need to check for overflow here */
  2473.             
  2474.             /* mask off 17 bits to be changed */
  2475.             *(long *)buf = *(long *)buf & 0xffe0e002;
  2476.             sign_unext( (new_val - 8) >> 2,17,&result);
  2477.             dis_assemble_17(result,&w1,&w2,&w);
  2478.             result = ( ( w2 << 2 ) | ( w1 << 16 ) | w );
  2479.             break;
  2480.             
  2481.             case 32:
  2482.             new_val = apply_field_selector(val,0,hppa_fixP->fx_r_field);
  2483.             result = new_val;    /* no transformation on result */
  2484.             *(long *)buf = 0;    /* clear out everything */
  2485.             break;
  2486.             
  2487.             case 0:
  2488.             return;
  2489.             
  2490.             default:
  2491.             as_bad("bad relocation type/fmt: 0x%02x/0x%02x",
  2492.                    fixP->fx_r_type, fmt);
  2493.             return;
  2494.         }
  2495.         buf[0] |= (result & 0xff000000) >> 24;
  2496.         buf[1] |= (result & 0x00ff0000) >> 16;
  2497.         buf[2] |= (result & 0x0000ff00) >> 8;
  2498.         buf[3] |= result & 0x000000ff;
  2499.         /* We've now adjusted for fx_addnumber, we can */
  2500.         /* forget it now. */
  2501.         fixP->fx_addnumber = 0;
  2502.     }
  2503.     else {
  2504.         printf("no hppa_fixup entry for this fixup (fixP = 0x%x, type = 0x%x)\n",
  2505.                fixP, fixP->fx_r_type);
  2506.     }
  2507. } /* md_apply_fix() */
  2508.  
  2509. /* Exactly what point is a PC-relative offset relative TO?
  2510.    On the PA, they're relative to the address of the offset.
  2511.    (??? Is this right?  FIXME-SOON) */
  2512. long md_pcrel_from(fixP)
  2513. fixS *fixP;
  2514. {
  2515.   return fixP->fx_where + fixP->fx_frag->fr_address;
  2516. } /* md_pcrel_from() */
  2517.  
  2518. int is_end_of_statement()
  2519. {
  2520.   return (   (*input_line_pointer == '\n')
  2521.       || (*input_line_pointer == ';')
  2522.       || (*input_line_pointer == '!') );
  2523. }
  2524.  
  2525. /* pa-aux.c -- Assembler for the PA - PA-RISC specific support routines */
  2526.  
  2527. struct aux_hdr_list *aux_hdr_root = NULL;
  2528.  
  2529. int print_errors = 1;
  2530.  
  2531. void pa_skip(s)
  2532.      char **s;
  2533. {
  2534.   while ( **s == ' ' || **s == '\t' )
  2535.     *s = *s + 1;
  2536. }
  2537.  
  2538. int pa_parse_number(s)
  2539.   char **s;
  2540. {
  2541.   int num;
  2542.   char *name;
  2543.   char c;
  2544.   symbolS *sym;
  2545.   int status;
  2546.   char * p = *s;
  2547.  
  2548.   while ( *p == ' ' || *p == '\t' )
  2549.     p = p + 1;
  2550.   num=-1; /* assume invalid number to begin with */
  2551.   if (isdigit(*p)) {
  2552.     num = 0; /* now we know it is a number */
  2553.  
  2554.     if ( *p == '0' && ( *(p+1) == 'x' || *(p+1) == 'X' ) ) { /* hex input */
  2555.       p = p + 2;
  2556.       while ( isdigit(*p) || ( (*p >= 'a') && (*p <= 'f') )
  2557.                        || ( (*p >= 'A') && (*p <= 'F') ) ){
  2558.     if ( isdigit(*p) )
  2559.       num = num*16 + *p-'0';
  2560.     else if ( *p >= 'a' && *p <= 'f' )
  2561.       num = num*16 + *p-'a' + 10; 
  2562.     else
  2563.       num = num*16 + *p-'A' + 10; 
  2564.     ++p;
  2565.       }
  2566.     }
  2567.     else {
  2568.       while (isdigit(*p)) {
  2569.     num= num*10 + *p-'0';
  2570.     ++p;
  2571.       }
  2572.     }
  2573.   }
  2574.   else if ( *p == '%' ) {   /* could be a pre-defined register */
  2575.     num = 0;
  2576.     name = p;
  2577.     p++;
  2578.     c = *p;
  2579.     /* tege hack: Special case for general registers
  2580.        as the general code makes a binary search with case translation,
  2581.        and is VERY slow.  */
  2582.     if (c == 'r') {
  2583.             p++;
  2584.         if ( *p == 'e' && *(p+1) == 't' && (*(p+2) == '0' || *(p+2) == '1') ) {
  2585.             p += 2;
  2586.             num = *p - '0' + 28;    /* r28 is ret0 */
  2587.             p++;
  2588.         }
  2589.             else if (!isdigit(*p))
  2590.                     as_bad("Undefined register: '%s'. ASSUMING 0",name);
  2591.             else {
  2592.                     do
  2593.                             num= num*10 + *p++ - '0';
  2594.                     while (isdigit(*p));
  2595.             }
  2596.     }
  2597.     else {
  2598.         while ( is_part_of_name(c) ) {
  2599.             p = p + 1;
  2600.             c = *p;
  2601.         }
  2602.         *p = 0;
  2603.         status = reg_name_search(name);
  2604.         if ( status >= 0 )
  2605.             num = status;
  2606.         else {
  2607.             if ( print_errors )
  2608.                 as_bad("Undefined register: '%s'. ASSUMING 0",name);
  2609.             else
  2610.                 num = -1;
  2611.         }
  2612.         *p = c;
  2613.     }
  2614.   }
  2615.   else {
  2616.     num = 0;
  2617.     name = p;
  2618.     c = *p;
  2619.     while ( is_part_of_name(c) ) {
  2620.       p = p + 1;
  2621.       c = *p;
  2622.     }
  2623.     *p = 0;
  2624.     if ( (sym = symbol_find(name)) != NULL ) {
  2625. #ifdef OBJ_SOM
  2626.       if ( sym->pa_sy_type == ST_ABSOLUTE ) {
  2627.     num = sym->pa_sy_value;
  2628. #else
  2629.       if ( S_GET_SEGMENT(sym) == &bfd_abs_section ) {
  2630.     num = S_GET_VALUE(sym);
  2631. #endif
  2632.       }
  2633.       else {
  2634.     if ( print_errors )
  2635.       as_bad("Non-absolute constant: '%s'. ASSUMING 0",name);
  2636.     else
  2637.       num = -1;
  2638.       }
  2639.     }
  2640.     else {
  2641.       if ( print_errors )
  2642.     as_bad("Undefined absolute constant: '%s'. ASSUMING 0",name);
  2643.       else
  2644.     num = -1;
  2645.     }
  2646.     *p = c;
  2647.   }
  2648.  
  2649.   *s = p;
  2650.   return num;
  2651. }
  2652.  
  2653. struct pd_reg {
  2654.     char    *name;
  2655.     int    value;
  2656. };
  2657.  
  2658. /*    List of registers that are pre-defined:
  2659.  
  2660.     General Registers:
  2661.  
  2662.     Name    Value        Name    Value
  2663.     %r0    0        %r16    16
  2664.     %r1    1        %r17    17
  2665.     %r2    2        %r18    18
  2666.     %r3    3        %r19    19
  2667.     %r4    4        %r20    20
  2668.     %r5    5        %r21    21
  2669.     %r6    6        %r22    22
  2670.     %r7    7        %r23    23
  2671.     %r8    8        %r24    24
  2672.     %r9    9        %r25    25
  2673.     %r10    10        %r26    26
  2674.     %r11    11        %r27    27
  2675.     %r12    12        %r28    28
  2676.     %r13    13        %r29    29
  2677.     %r14    14        %r30    30
  2678.     %r15    15        %r31    31
  2679.  
  2680.     Floating-point Registers:
  2681.     [NOTE:  Also includes L and R versions of these (e.g. %fr19L, %fr19R)]
  2682.  
  2683.     Name    Value        Name    Value
  2684.     %fr0    0        %fr16    16
  2685.     %fr1    1        %fr17    17
  2686.     %fr2    2        %fr18    18
  2687.     %fr3    3        %fr19    19
  2688.     %fr4    4        %fr20    20
  2689.     %fr5    5        %fr21    21
  2690.     %fr6    6        %fr22    22
  2691.     %fr7    7        %fr23    23
  2692.         %fr8    8        %fr24    24
  2693.     %fr9    9        %fr25    25
  2694.     %fr10    10        %fr26    26
  2695.     %fr11    11        %fr27    27
  2696.     %fr12    12        %fr28    28
  2697.     %fr13    13        %fr29    29
  2698.     %fr14    14        %fr30    30
  2699.     %fr15    15        %fr31    31
  2700.  
  2701.     Space Registers:
  2702.  
  2703.     Name    Value        Name    Value
  2704.     %sr0    0        %sr4    4
  2705.     %sr1    1        %sr5    5
  2706.     %sr2    2        %sr6    6
  2707.     %sr3    3        %sr7    7
  2708.  
  2709.     Control registers and their synonyms:
  2710.  
  2711.     Names            Value
  2712.     %cr0    %rctr        0
  2713.     %cr8    %pidr1        8
  2714.     %cr9    %pidr2        9
  2715.     %cr10    %ccr        10
  2716.     %cr11    %sar        11
  2717.     %cr12    %pidr3        12
  2718.     %cr13    %pidr4        13
  2719.     %cr14    %iva        14
  2720.     %cr15    %eiem        15
  2721.     %cr16    %itmr        16
  2722.     %cr17    %pcsq        17
  2723.     %cr18    %pcoq        18
  2724.     %cr19    %iir        19
  2725.     %cr20    %isr        20
  2726.     %cr21    %ior        21
  2727.     %cr22    %ipsw        22
  2728.     %cr23    %eirr        23
  2729.     %cr24    %tr0 %ppda    24
  2730.     %cr25    %tr1 %hta    25
  2731.     %cr26    %tr2        26
  2732.     %cr27    %tr3        27
  2733.     %cr28    %tr4        28
  2734.     %cr29    %tr5        29
  2735.     %cr30    %tr6        30
  2736.     %cr31    %tr7        31
  2737.  
  2738.     Miscellaneous registers and their synonyms:
  2739.  
  2740.     Names            Value
  2741.     %arg0            26
  2742.     %arg1            25
  2743.     %arg2            24
  2744.     %arg3            23
  2745.     %sp            30
  2746.     %ret0            28
  2747.     %ret1            29
  2748. */
  2749.  
  2750. /* This table is sorted. Suitable for searching by a binary search. */
  2751.  
  2752. static struct pd_reg pre_defined_registers[] = {
  2753.     {    "%arg0",    26    },
  2754.     {    "%arg1",    25    },
  2755.     {    "%arg2",    24    },
  2756.     {    "%arg3",    23    },
  2757.     {    "%cr0",        0    },
  2758.     {    "%cr10",    10    },
  2759.     {    "%cr11",    11    },
  2760.     {    "%cr12",    12    },
  2761.     {    "%cr13",    13    },
  2762.     {    "%cr14",    14    },
  2763.     {    "%cr15",    15    },
  2764.     {    "%cr16",    16    },
  2765.     {    "%cr17",    17    },
  2766.     {    "%cr18",    18    },
  2767.     {    "%cr19",    19    },
  2768.     {    "%cr20",    20    },
  2769.     {    "%cr21",    21    },
  2770.     {    "%cr22",    22    },
  2771.     {    "%cr23",    23    },
  2772.     {    "%cr24",    24    },
  2773.     {    "%cr25",    25    },
  2774.     {    "%cr26",    26    },
  2775.     {    "%cr27",    27    },
  2776.     {    "%cr28",    28    },
  2777.     {    "%cr29",    29    },
  2778.     {    "%cr30",    30    },
  2779.     {    "%cr31",    31    },
  2780.     {    "%cr8",        8    },
  2781.     {    "%cr9",        9    },
  2782.     {    "%eiem",    15    },
  2783.     {    "%eirr",    23    },
  2784.     {    "%fr0",        0    },
  2785.     {    "%fr0L",    0    },
  2786.     {    "%fr0R",    0    },
  2787.     {    "%fr1",        1    },
  2788.     {    "%fr10",    10    },
  2789.     {    "%fr10L",    10    },
  2790.     {    "%fr10R",    10    },
  2791.     {    "%fr11",    11    },
  2792.     {    "%fr11L",    11    },
  2793.     {    "%fr11R",    11    },
  2794.     {    "%fr12",    12    },
  2795.     {    "%fr12L",    12    },
  2796.     {    "%fr12R",    12    },
  2797.     {    "%fr13",    13    },
  2798.     {    "%fr13L",    13    },
  2799.     {    "%fr13R",    13    },
  2800.     {    "%fr14",    14    },
  2801.     {    "%fr14L",    14    },
  2802.     {    "%fr14R",    14    },
  2803.     {    "%fr15",    15    },
  2804.     {    "%fr15L",    15    },
  2805.     {    "%fr15R",    15    },
  2806.     {    "%fr16",    16    },
  2807.     {    "%fr16L",    16    },
  2808.     {    "%fr16R",    16    },
  2809.     {    "%fr17",    17    },
  2810.     {    "%fr17L",    17    },
  2811.     {    "%fr17R",    17    },
  2812.     {    "%fr18",    18    },
  2813.     {    "%fr18L",    18    },
  2814.     {    "%fr18R",    18    },
  2815.     {    "%fr19",    19    },
  2816.     {    "%fr19L",    19    },
  2817.     {    "%fr19R",    19    },
  2818.     {    "%fr1L",    1    },
  2819.     {    "%fr1R",    1    },
  2820.     {    "%fr2",        2    },
  2821.     {    "%fr20",    20    },
  2822.     {    "%fr20L",    20    },
  2823.     {    "%fr20R",    20    },
  2824.     {    "%fr21",    21    },
  2825.     {    "%fr21L",    21    },
  2826.     {    "%fr21R",    21    },
  2827.     {    "%fr22",    22    },
  2828.     {    "%fr22L",    22    },
  2829.     {    "%fr22R",    22    },
  2830.     {    "%fr23",    23    },
  2831.     {    "%fr23L",    23    },
  2832.     {    "%fr23R",    23    },
  2833.     {    "%fr24",    24    },
  2834.     {    "%fr24L",    24    },
  2835.     {    "%fr24R",    24    },
  2836.     {    "%fr25",    25    },
  2837.     {    "%fr25L",    25    },
  2838.     {    "%fr25R",    25    },
  2839.     {    "%fr26",    26    },
  2840.     {    "%fr26L",    26    },
  2841.     {    "%fr26R",    26    },
  2842.     {    "%fr27",    27    },
  2843.     {    "%fr27L",    27    },
  2844.     {    "%fr27R",    27    },
  2845.     {    "%fr28",    28    },
  2846.     {    "%fr28L",    28    },
  2847.     {    "%fr28R",    28    },
  2848.     {    "%fr29",    29    },
  2849.     {    "%fr29L",    29    },
  2850.     {    "%fr29R",    29    },
  2851.     {    "%fr2L",    2    },
  2852.     {    "%fr2R",    2    },
  2853.     {    "%fr3",        3    },
  2854.     {    "%fr30",    30    },
  2855.     {    "%fr30L",    30    },
  2856.     {    "%fr30R",    30    },
  2857.     {    "%fr31",    31    },
  2858.     {    "%fr31L",    31    },
  2859.     {    "%fr31R",    31    },
  2860.     {    "%fr3L",    3    },
  2861.     {    "%fr3R",    3    },
  2862.     {    "%fr4",        4    },
  2863.     {    "%fr4L",    4    },
  2864.     {    "%fr4R",    4    },
  2865.     {    "%fr5",        5    },
  2866.     {    "%fr5L",    5    },
  2867.     {    "%fr5R",    5    },
  2868.     {    "%fr6",        6    },
  2869.     {    "%fr6L",    6    },
  2870.     {    "%fr6R",    6    },
  2871.     {    "%fr7",        7    },
  2872.     {    "%fr7L",    7    },
  2873.     {    "%fr7R",    7    },
  2874.     {    "%fr8",        8    },
  2875.     {    "%fr8L",    8    },
  2876.     {    "%fr8R",    8    },
  2877.     {    "%fr9",        9    },
  2878.     {    "%fr9L",    9    },
  2879.     {    "%fr9R",    9    },
  2880.     {    "%hta",        25    },
  2881.     {    "%iir",        19    },
  2882.     {    "%ior",        21    },
  2883.     {    "%ipsw",    22    },
  2884.     {    "%isr",        20    },
  2885.     {    "%itmr",    16    },
  2886.     {    "%iva",        14    },
  2887.     {    "%pcoq",    18    },
  2888.     {    "%pcsq",    17    },
  2889.     {    "%pidr1",    8    },
  2890.     {    "%pidr2",    9    },
  2891.     {    "%pidr3",    12    },
  2892.     {    "%pidr4",    13    },
  2893.     {    "%ppda",    24    },
  2894.     {    "%r0",    0    },
  2895.     {    "%r1",    1    },
  2896.     {    "%r10",    10    },
  2897.     {    "%r11",    11    },
  2898.     {    "%r12",    12    },
  2899.     {    "%r13",    13    },
  2900.     {    "%r14",    14    },
  2901.     {    "%r15",    15    },
  2902.     {    "%r16",    16    },
  2903.     {    "%r17",    17    },
  2904.     {    "%r18",    18    },
  2905.     {    "%r19",    19    },
  2906.     {    "%r2",    2    },
  2907.     {    "%r20",    20    },
  2908.     {    "%r21",    21    },
  2909.     {    "%r22",    22    },
  2910.     {    "%r23",    23    },
  2911.     {    "%r24",    24    },
  2912.     {    "%r25",    25    },
  2913.     {    "%r26",    26    },
  2914.     {    "%r27",    27    },
  2915.     {    "%r28",    28    },
  2916.     {    "%r29",    29    },
  2917.     {    "%r3",    3    },
  2918.     {    "%r30",    30    },
  2919.     {    "%r31",    31    },
  2920.     {    "%r4",    4    },
  2921.     {    "%r4L",    4    },
  2922.     {    "%r4R",    4    },
  2923.     {    "%r5",    5    },
  2924.     {    "%r5L",    5    },
  2925.     {    "%r5R",    5    },
  2926.     {    "%r6",    6    },
  2927.     {    "%r6L",    6    },
  2928.     {    "%r6R",    6    },
  2929.     {    "%r7",    7    },
  2930.     {    "%r7L",    7    },
  2931.     {    "%r7R",    7    },
  2932.     {    "%r8",    8    },
  2933.     {    "%r8L",    8    },
  2934.     {    "%r8R",    8    },
  2935.     {    "%r9",    9    },
  2936.     {    "%r9L",    9    },
  2937.     {    "%r9R",    9    },
  2938.     {    "%rctr",0    },
  2939.     {    "%ret0",28    },
  2940.     {    "%ret1",29    },
  2941.     {    "%sar",    11    },
  2942.     {    "%sp",    30    },
  2943.     {    "%sr0",    0    },
  2944.     {    "%sr1",    1    },
  2945.     {    "%sr2",    2    },
  2946.     {    "%sr3",    3    },
  2947.     {    "%sr4",    4    },
  2948.     {    "%sr5",    5    },
  2949.     {    "%sr6",    6    },
  2950.     {    "%sr7",    7    },
  2951.     {    "%tr0",    24    },
  2952.     {    "%tr1",    25    },
  2953.     {    "%tr2",    26    },
  2954.     {    "%tr3",    27    },
  2955.     {    "%tr4",    28    },
  2956.     {    "%tr5",    29    },
  2957.     {    "%tr6",    30    },
  2958.     {    "%tr7",    31    }
  2959. };
  2960.  
  2961. #define REG_NAME_CNT    (sizeof(pre_defined_registers) / sizeof(struct pd_reg))
  2962.  
  2963. int reg_name_search(name)
  2964.     char    *name;
  2965. {
  2966.     int x,l,r;
  2967.  
  2968.     l = 0;
  2969.     r = REG_NAME_CNT - 1;
  2970.  
  2971.     do {
  2972.         x = (l + r) / 2;
  2973.         if (strcasecmp(name,pre_defined_registers[x].name) < 0)
  2974.             r = x - 1;
  2975.         else
  2976.             l = x + 1;
  2977.     } while ( !( (strcasecmp(name,pre_defined_registers[x].name) == 0) ||
  2978.              (l > r) ) );
  2979.  
  2980.     if ( strcasecmp(name,pre_defined_registers[x].name) == 0 )
  2981.         return(pre_defined_registers[x].value);
  2982.     else
  2983.         return(-1);
  2984.  
  2985. }
  2986.  
  2987. int is_pre_defined_register(s)
  2988.      char *s;
  2989. {
  2990.     if ( reg_name_search(s) >= 0 )
  2991.         return(TRUE);
  2992.     else
  2993.         return(FALSE);
  2994. }
  2995.     
  2996. int is_R_select(s)
  2997.   char *s;
  2998. {
  2999.  
  3000.   if ( *s == 'R' || *s == 'r' )
  3001.     return(TRUE);
  3002.   else
  3003.     return(FALSE);    
  3004. }
  3005.  
  3006. int is_L_select(s)
  3007.   char *s;
  3008. {
  3009.  
  3010.   if ( *s == 'L' || *s == 'l' )
  3011.     return(TRUE);
  3012.   else
  3013.     return(FALSE);    
  3014. }
  3015.  
  3016. int need_89_opcode(insn,result)
  3017.      struct pa_it *insn;
  3018.      struct pa_89_fp_reg_struct *result;
  3019. {
  3020.   /* if ( result->L_R_select == 1 || insn->fpof1 == DBL || insn->fpof2 == DBL ) */
  3021.   /* if (result->L_R_select == 1 && !(insn->fpof1 == DBL || insn->fpof2 == DBL) ) */
  3022.   if ( result->L_R_select == 1 && !(insn->fpof1 == DBL && insn->fpof2 == DBL) )
  3023.   /* if ( insn->fpof1 == DBL || insn->fpof2 == DBL ) */
  3024.     return TRUE;
  3025.   else
  3026.     return FALSE;
  3027. }
  3028.  
  3029. int
  3030. pa_89_parse_number(s,result)
  3031.      char **s;
  3032.      struct pa_89_fp_reg_struct *result;
  3033. {
  3034.   int num;
  3035.   char *name;
  3036.   char c;
  3037.   symbolS *sym;
  3038.   int status;
  3039.   char * p = *s;
  3040.  
  3041.   while ( *p == ' ' || *p == '\t' )
  3042.     p = p + 1;
  3043.   num=-1; /* assume invalid number to begin with */
  3044.   result->number_part = -1;
  3045.   result->L_R_select  = -1;
  3046.  
  3047.   if (isdigit(*p)) {
  3048.     num = 0; /* now we know it is a number */
  3049.  
  3050.     if ( *p == '0' && ( *(p+1) == 'x' || *(p+1) == 'X' ) ) { /* hex input */
  3051.       p = p + 2;
  3052.       while ( isdigit(*p) || ( (*p >= 'a') && (*p <= 'f') )
  3053.                        || ( (*p >= 'A') && (*p <= 'F') ) ){
  3054.     if ( isdigit(*p) )
  3055.       num = num*16 + *p-'0';
  3056.     else if ( *p >= 'a' && *p <= 'f' )
  3057.       num = num*16 + *p-'a' + 10; 
  3058.     else
  3059.       num = num*16 + *p-'A' + 10; 
  3060.     ++p;
  3061.       }
  3062.     }
  3063.     else {
  3064.       while (isdigit(*p)) {
  3065.     num= num*10 + *p-'0';
  3066.     ++p;
  3067.       }
  3068.     }
  3069.  
  3070.     result->number_part = num;
  3071.  
  3072.     if ( is_R_select(p) ) {
  3073.       result->L_R_select = 1;
  3074.       ++p;
  3075.     }
  3076.     else if ( is_L_select(p) ) {
  3077.       result->L_R_select = 0;
  3078.       ++p;
  3079.     }
  3080.     else
  3081.       result->L_R_select = 0;
  3082.  
  3083.   }
  3084.   else if ( *p == '%' ) {          /* could be a pre-defined register */
  3085.     num = 0;
  3086.     name = p;
  3087.     p++;
  3088.     c = *p;
  3089.     /* tege hack: Special case for general registers
  3090.        as the general code makes a binary search with case translation,
  3091.        and is VERY slow.  */
  3092.     if (c == 'r') {
  3093.       p++;
  3094.       if ( *p == 'e' && *(p+1) == 't' && (*(p+2) == '0' || *(p+2) == '1') ) {
  3095.           p += 2;
  3096.           num = *p - '0' + 28;    /* r28 is ret0 */
  3097.           p++;
  3098.       }
  3099.       else if (!isdigit(*p))
  3100.         as_bad("Undefined register: '%s'. ASSUMING 0",name);
  3101.       else {
  3102.           do
  3103.             num= num*10 + *p++ - '0';
  3104.           while (isdigit(*p));
  3105.         }
  3106.       }
  3107.     else {
  3108.         while ( is_part_of_name(c) ) {
  3109.             p = p + 1;
  3110.             c = *p;
  3111.         }
  3112.         *p = 0;
  3113.         status = reg_name_search(name);
  3114.         if ( status >= 0 )
  3115.             num = status;
  3116.         else {
  3117.             if ( print_errors )
  3118.                 as_bad("Undefined register: '%s'. ASSUMING 0",name);
  3119.             else
  3120.                 num = -1;
  3121.         }
  3122.         *p = c;
  3123.     }
  3124.  
  3125.     result->number_part = num;
  3126.  
  3127.     if ( is_R_select(p-1) )
  3128.       result->L_R_select = 1;
  3129.     else if ( is_L_select(p-1) )
  3130.       result->L_R_select = 0;
  3131.     else
  3132.       result->L_R_select = 0;
  3133.  
  3134.   }
  3135.   else {
  3136.     num = 0;
  3137.     name = p;
  3138.     c = *p;
  3139.     while ( is_part_of_name(c) ) {
  3140.       p = p + 1;
  3141.       c = *p;
  3142.     }
  3143.     *p = 0;
  3144.     if ( (sym = symbol_find(name)) != NULL ) {
  3145. #ifdef OBJ_SOM
  3146.       if ( sym->pa_sy_type == ST_ABSOLUTE ) {
  3147.     num = sym->pa_sy_value;
  3148. #else
  3149.       if ( S_GET_SEGMENT(sym) == &bfd_abs_section ) {
  3150.     num = S_GET_VALUE(sym);
  3151. #endif
  3152.       }
  3153.       else {
  3154.     if ( print_errors )
  3155.       as_bad("Non-absolute constant: '%s'. ASSUMING 0",name);
  3156.     else
  3157.       num = -1;
  3158.       }
  3159.     }
  3160.     else {
  3161.       if ( print_errors )
  3162.     as_bad("Undefined absolute constant: '%s'. ASSUMING 0",name);
  3163.       else
  3164.     num = -1;
  3165.     }
  3166.     *p = c;
  3167.     result->number_part = num;
  3168.  
  3169.     if ( is_R_select(p-1) )
  3170.     result->L_R_select = 1;
  3171.     else if ( is_L_select(p-1) )
  3172.     result->L_R_select = 0;
  3173.     else
  3174.     result->L_R_select = 0;
  3175.  
  3176.   }
  3177.  
  3178.   *s = p;
  3179.   return num;
  3180.  
  3181. }
  3182.  
  3183. int pa_parse_fp_cmp_cond(s)
  3184.   char **s;
  3185. {
  3186.   int cond,i;
  3187.   struct possibleS {
  3188.     char *string;
  3189.     int cond;
  3190.   };
  3191.  
  3192.   /* 
  3193.      This table is sorted by order of the length of the string. This is so we
  3194.      check for <> before we check for <. If we had a <> and checked for < first,
  3195.      we would get a false match.
  3196.    */
  3197.   static struct possibleS poss[] =
  3198.     {
  3199.       { "false?", 0 },
  3200.       { "false",  1 },
  3201.       { "true?",  30 },
  3202.       { "true",   31 },
  3203.       { "!<=>",   3 },
  3204.       { "!?>=",   8 },
  3205.       { "!?<=",   16 },
  3206.       { "!<>",    7 },
  3207.       { "!>=",    11 },
  3208.       { "!?>",    12 },
  3209.       { "?<=",    14 },
  3210.       { "!<=",    19 },
  3211.       { "!?<",    20 },
  3212.       { "?>=",    22 },
  3213.       { "!?=",    24 },
  3214.       { "!=t",    27 },
  3215.       { "<=>",    29 },
  3216.       { "=t",     5 },
  3217.       { "?=",     6 },
  3218.       { "?<",     10 },
  3219.       { "<=",     13 },
  3220.       { "!>",     15 },
  3221.       { "?>",     18 },
  3222.       { ">=",     21 },
  3223.       { "!<",     23 },
  3224.       { "<>",     25 },
  3225.       { "!=",     26 },
  3226.       { "!?",     28 },
  3227.       { "?",      2 },
  3228.       { "=",      4 },
  3229.       { "<",      9 },
  3230.       { ">",      17 }
  3231.     };
  3232.  
  3233.   cond=0;
  3234.  
  3235.   for ( i = 0; i < 32; i++ ) {
  3236.     if ( strncasecmp(*s,poss[i].string,strlen(poss[i].string)) == 0 ) {
  3237.       cond = poss[i].cond;
  3238.       *s += strlen(poss[i].string);
  3239.       while ( **s == ' ' || **s == '\t' )
  3240.     *s = *s + 1;
  3241.       return cond;
  3242.     }
  3243.   }
  3244.  
  3245.   as_bad("Illegal FP Compare Condition: %c",**s);
  3246.   return 0;
  3247. }
  3248.  
  3249. FP_Operand_Format pa_parse_fp_format(s)
  3250.      char **s;
  3251. {
  3252.   int f;
  3253.  
  3254.   f = SGL;
  3255.   if ( **s == ',' ) {
  3256.     *s += 1;
  3257.     if ( strncasecmp(*s,"sgl",3) == 0 ) {
  3258.       f = SGL;
  3259.       *s += 4;
  3260.     }
  3261.     else if ( strncasecmp(*s,"dbl",3) == 0 ) {
  3262.       f = DBL;
  3263.       *s += 4;
  3264.     }
  3265.     else if ( strncasecmp(*s,"quad",4) == 0 ) {
  3266.       f = QUAD;
  3267.       *s += 5;
  3268.     }
  3269.     else {
  3270.       f = ILLEGAL_FMT;
  3271.       as_bad("Unrecognized FP Operand Format: %3s",*s);
  3272.     }
  3273.   }
  3274.   while ( **s == ' ' || **s == '\t' || **s == 0 )
  3275.     *s = *s + 1;
  3276.  
  3277.   return f;
  3278. }
  3279.  
  3280. #if defined(OBJ_ELF)
  3281. int pa_chk_field_selector(str)
  3282. char **str;
  3283. {
  3284.   int selector;
  3285.   struct selector_entry {
  3286.     char *prefix;
  3287.     int field_selector;
  3288.   };
  3289.   static struct selector_entry selector_table[] = {
  3290.     { "F'",  e_fsel  },
  3291.     { "F%",  e_fsel  },
  3292.     { "LS'", e_lssel },
  3293.     { "LS%", e_lssel },
  3294.     { "RS'", e_rssel },
  3295.     { "RS%", e_rssel },
  3296.     { "L'",  e_lsel  },
  3297.     { "L%",  e_lsel  },
  3298.     { "R'",  e_rsel  },
  3299.     { "R%",  e_rsel  },
  3300.     { "LD'", e_ldsel },
  3301.     { "LD%", e_ldsel },
  3302.     { "RD'", e_rdsel },
  3303.     { "RD%", e_rdsel },
  3304.     { "LR'", e_lrsel },
  3305.     { "LR%", e_lrsel },
  3306.     { "RR'", e_rrsel },
  3307.     { "RR%", e_rrsel },
  3308.     { "P'",  e_psel },
  3309.     { "P%",  e_psel },
  3310.     { "RP'", e_rpsel },
  3311.     { "RP%", e_rpsel },
  3312.     { "LP'", e_lpsel },
  3313.     { "LP%", e_lpsel },
  3314.     { "T'",  e_tsel },
  3315.     { "T%",  e_tsel },
  3316.     { "RT'", e_rtsel },
  3317.     { "RT%", e_rtsel },
  3318.     { "LT'", e_ltsel },
  3319.     { "LT%", e_ltsel },
  3320.     { NULL,  e_fsel  }
  3321.   };
  3322.   struct selector_entry *tableP;
  3323.  
  3324.   selector = e_fsel;
  3325.  
  3326.   while ( **str == ' '  || **str == '\t' || **str == '\n' || **str == '\f' )
  3327.       {
  3328.           *str = *str + 1;
  3329.       }
  3330.   for ( tableP = selector_table; tableP->prefix; tableP++ )
  3331.       {
  3332.           if ( strncasecmp(tableP->prefix,*str,strlen(tableP->prefix)) == 0 )
  3333.           {
  3334.               *str += strlen(tableP->prefix);
  3335.               selector = tableP->field_selector;
  3336.               break;
  3337.           }
  3338.       }
  3339.   return selector;
  3340. }
  3341.  
  3342. int
  3343. getExpression(str)
  3344.     char *str;
  3345. {
  3346.     char *save_in;
  3347.     asection * seg;
  3348.  
  3349.     save_in = input_line_pointer;
  3350.     input_line_pointer = str;
  3351.     seg = expression(&the_insn.exp);
  3352.  
  3353.   if (! (seg == &bfd_abs_section
  3354.      || seg == &bfd_und_section
  3355.      || seg == text_section
  3356.      || seg == data_section
  3357.      || seg == bss_section
  3358.      || seg == diff_section
  3359.      || seg == big_section
  3360.      || seg == absent_section))
  3361.     {
  3362.     the_insn.error = "bad segment";
  3363.     expr_end = input_line_pointer;
  3364.     input_line_pointer=save_in;
  3365.     return 1;
  3366.     }
  3367.     expr_end = input_line_pointer;
  3368.     input_line_pointer = save_in;
  3369.     return 0;
  3370. }
  3371.  
  3372. int
  3373. getAbsoluteExpression(str)
  3374.     char *str;
  3375. {
  3376.     char *save_in;
  3377.     asection * seg;
  3378.  
  3379.     save_in = input_line_pointer;
  3380.     input_line_pointer = str;
  3381.     seg = expression(&the_insn.exp);
  3382.  
  3383.     if ( seg != &bfd_abs_section ) {
  3384.     the_insn.error = "segment should be ABSOLUTE";
  3385.     expr_end = input_line_pointer;
  3386.     input_line_pointer=save_in;
  3387.     return 1;
  3388.     }
  3389.     expr_end = input_line_pointer;
  3390.     input_line_pointer = save_in;
  3391.     return 0;
  3392. }
  3393.  
  3394. #else
  3395. int
  3396. getExpression(str)
  3397.     char *str;
  3398. {
  3399.     char *save_in;
  3400.     segT seg;
  3401.  
  3402.     save_in = input_line_pointer;
  3403.     input_line_pointer = str;
  3404.     switch (seg = expression(&the_insn.exp)) {
  3405.  
  3406.     case SEG_ABSOLUTE:
  3407.     case SEG_TEXT:
  3408.     case SEG_DATA:
  3409.     case SEG_BSS:
  3410.     case SEG_UNKNOWN:
  3411.     case SEG_DIFFERENCE:
  3412.     case SEG_BIG:
  3413.     case SEG_GDB:
  3414.     case SEG_MILLICODE:
  3415.     case SEG_NONE:
  3416.     break;
  3417.  
  3418.     default:
  3419.     the_insn.error = "illegal segment";
  3420.     expr_end = input_line_pointer;
  3421.     input_line_pointer=save_in;
  3422.     return 1;
  3423.     }
  3424.     expr_end = input_line_pointer;
  3425.     input_line_pointer = save_in;
  3426.     return 0;
  3427. }
  3428.  
  3429. int
  3430. getAbsoluteExpression(str)
  3431.     char *str;
  3432. {
  3433.     char *save_in;
  3434.     segT seg;
  3435.  
  3436.     save_in = input_line_pointer;
  3437.     input_line_pointer = str;
  3438.     switch (seg = expression(&the_insn.exp)) {
  3439.  
  3440.     case SEG_ABSOLUTE:
  3441.     break;
  3442.  
  3443.     default:
  3444.     the_insn.error = "segment should be ABSOLUTE";
  3445.     expr_end = input_line_pointer;
  3446.     input_line_pointer=save_in;
  3447.     return 1;
  3448.     }
  3449.     expr_end = input_line_pointer;
  3450.     input_line_pointer = save_in;
  3451.     return 0;
  3452. }
  3453.  
  3454. #endif
  3455.  
  3456. int evaluateAbsolute(exp,field_selector)
  3457.      expressionS exp;
  3458.      int field_selector;
  3459. {
  3460.   int value;
  3461.  
  3462.   value = exp.X_add_number;
  3463.  
  3464.   if ( exp.X_add_symbol ) {
  3465.     value += S_GET_VALUE(exp.X_add_symbol);
  3466.   }
  3467.   if ( exp.X_subtract_symbol ) {
  3468.     value -= S_GET_VALUE(exp.X_subtract_symbol);
  3469.   }
  3470.  
  3471.   switch (field_selector) {
  3472.   case e_fsel:        /* F  : no change                      */
  3473.     break;
  3474.  
  3475.   case e_lssel:       /* LS : if (bit 21) then add 0x800
  3476.                               arithmetic shift right 11 bits */
  3477.     if ( value & 0x00000400 )
  3478.       value += 0x800;
  3479.     value = (value & 0xfffff800) >> 11;
  3480.     break;
  3481.  
  3482.   case e_rssel:       /* RS : Sign extend from bit 21        */
  3483.     if ( value & 0x00000400 )
  3484.         value |= 0xfffff800;
  3485.     else
  3486.         value &= 0x7ff;
  3487.     break;
  3488.  
  3489.   case e_lsel:        /* L  : Arithmetic shift right 11 bits */
  3490.     value = (value & 0xfffff800) >> 11;
  3491.     break;
  3492.  
  3493.   case e_rsel:        /* R  : Set bits 0-20 to zero          */
  3494.     value = value & 0x7ff;
  3495.     break;
  3496.  
  3497.   case e_ldsel:       /* LD : Add 0x800, arithmetic shift
  3498.                               right 11 bits                  */
  3499.     value += 0x800;
  3500.     value = (value & 0xfffff800) >> 11;    
  3501.     break;
  3502.  
  3503.   case e_rdsel:       /* RD : Set bits 0-20 to one           */
  3504.     value |= 0xfffff800;
  3505.     break;
  3506.  
  3507.   case e_lrsel:       /* LR : L with "rounded" constant      */
  3508.     /* XXX: this isn't right.  Need to add a "rounded" constant */
  3509.     /* XXX: (presumably from X_add_number)                      */
  3510.     value = (value & 0xfffff800) >> 11;
  3511.     break;
  3512.  
  3513.   case e_rrsel:       /* RR : R with "rounded" constant      */
  3514.     /* XXX: this isn't right.  Need to add a "rounded" constant */
  3515.     /* XXX: (presumably from X_add_number)                      */
  3516.     value = value & 0x7ff;
  3517.     break;
  3518.  
  3519.   default:
  3520.     BAD_CASE(field_selector);
  3521.     break;
  3522.   }
  3523.   return value;
  3524. }
  3525.  
  3526. int pa_build_arg_reloc(type_name)
  3527.      char *type_name;
  3528. {
  3529.  
  3530.   if ( strncasecmp(type_name,"no",2) == 0 ) {
  3531.     return 0;
  3532.   }
  3533.   if ( strncasecmp(type_name,"gr",2) == 0 ) {
  3534.     return 1;
  3535.   }
  3536.   else if ( strncasecmp(type_name,"fr",2) == 0 ) {
  3537.     return 2;
  3538.   }
  3539.   else if ( strncasecmp(type_name,"fu",2) == 0 ) {
  3540.     return 3;
  3541.   }
  3542.   else
  3543.     as_bad("Unrecognized argument location: %s\n",type_name);
  3544.  
  3545.   return 0;
  3546. }
  3547.  
  3548. unsigned int pa_align_arg_reloc(reg,arg_reloc)
  3549.      unsigned int reg;
  3550.      unsigned int arg_reloc;
  3551. {
  3552.   unsigned int new_reloc;
  3553.  
  3554.   new_reloc = arg_reloc;
  3555.   switch(reg) {
  3556.   case 0:
  3557.     new_reloc <<= 8;
  3558.     break;
  3559.   case 1:
  3560.     new_reloc <<= 6;
  3561.     break;
  3562.   case 2:
  3563.     new_reloc <<= 4;
  3564.     break;
  3565.   case 3:
  3566.     new_reloc <<= 2;
  3567.     break;
  3568.   default:
  3569.     as_bad("Illegal argument description: %d",reg);
  3570.   }
  3571.  
  3572.   return new_reloc;
  3573. }
  3574.  
  3575. int pa_parse_nullif(s)
  3576.      char **s;
  3577. {
  3578.   int nullif;
  3579.  
  3580.   nullif = 0;
  3581.   if ( **s == ',' ) {
  3582.     *s = *s + 1;
  3583.     if ( strncasecmp(*s,"n",1) == 0 )
  3584.       nullif = 1;
  3585.     else {
  3586.       as_bad("Unrecognized Nullification: (%c)",**s);
  3587.       nullif = 0;
  3588.     }
  3589.     *s = *s + 1;
  3590.   }
  3591.   while ( **s == ' ' || **s == '\t' )
  3592.     *s = *s + 1;
  3593.  
  3594.   return nullif;
  3595. }
  3596.  
  3597. #if 0
  3598. int pa_parse_nonneg_cmpsub_cmpltr(s)
  3599.      char **s;
  3600. {
  3601.   int cmpltr;
  3602.   char *name;
  3603.   char c;
  3604.  
  3605.   cmpltr = -1;
  3606.   /** cmpltr = 0; **/
  3607.   if ( **s == ',' ) {
  3608.     *s+=1;
  3609.     name = *s;
  3610.     while ( **s != ',' && **s != ' ' && **s != '\t' )
  3611.       *s += 1;
  3612.     c = **s;
  3613.     **s = 0x00;
  3614.     if ( strcmp(name,"=") == 0 ) {
  3615.       cmpltr = 1;
  3616.     }
  3617.     else if ( strcmp(name,"<") == 0 ) {
  3618.       cmpltr = 2;
  3619.     }
  3620.     else if ( strcmp(name,"<=") == 0 ) {
  3621.       cmpltr = 3;
  3622.     }
  3623.     else if ( strcmp(name,"<<") == 0 ) {
  3624.       cmpltr = 4;
  3625.     }
  3626.     else if ( strcmp(name,"<<=") == 0 ) {
  3627.       cmpltr = 5;
  3628.     }
  3629.     else if ( strcasecmp(name,"sv") == 0 ) {
  3630.       cmpltr = 6;
  3631.     }
  3632.     else if ( strcasecmp(name,"od") == 0 ) {
  3633.       cmpltr = 7;
  3634.     }
  3635.     /**
  3636.     else
  3637.       cmpltr = -1;
  3638.     **/
  3639.     **s = c;
  3640.   }
  3641.   if ( cmpltr >= 0 ) {
  3642.     while ( **s == ' ' || **s == '\t' )
  3643.       *s = *s + 1;
  3644.   }
  3645.  
  3646.   return cmpltr;
  3647. }
  3648. #endif
  3649. int pa_parse_nonneg_cmpsub_cmpltr(s)
  3650.      char **s;
  3651. {
  3652.   int cmpltr;
  3653.   char *name;
  3654.   char c;
  3655.  
  3656.   cmpltr = 0;
  3657.   if ( **s == ',' ) {
  3658.     *s+=1;
  3659.     name = *s;
  3660.     while ( **s != ',' && **s != ' ' && **s != '\t' )
  3661.       *s += 1;
  3662.     c = **s;
  3663.     **s = 0x00;
  3664.     if ( strcmp(name,"=") == 0 ) {
  3665.       cmpltr = 1;
  3666.     }
  3667.     else if ( strcmp(name,"<") == 0 ) {
  3668.       cmpltr = 2;
  3669.     }
  3670.     else if ( strcmp(name,"<=") == 0 ) {
  3671.       cmpltr = 3;
  3672.     }
  3673.     else if ( strcmp(name,"<<") == 0 ) {
  3674.       cmpltr = 4;
  3675.     }
  3676.     else if ( strcmp(name,"<<=") == 0 ) {
  3677.       cmpltr = 5;
  3678.     }
  3679.     else if ( strcasecmp(name,"sv") == 0 ) {
  3680.       cmpltr = 6;
  3681.     }
  3682.     else if ( strcasecmp(name,"od") == 0 ) {
  3683.       cmpltr = 7;
  3684.     }
  3685.     else
  3686.       cmpltr = -1;
  3687.     **s = c;
  3688.   }
  3689.   if ( cmpltr >= 0 ) {
  3690.     while ( **s == ' ' || **s == '\t' )
  3691.       *s = *s + 1;
  3692.   }
  3693.  
  3694.   return cmpltr;
  3695. }
  3696.  
  3697. int pa_parse_neg_cmpsub_cmpltr(s)
  3698.      char **s;
  3699. {
  3700.   int cmpltr;
  3701.   char *name;
  3702.   char c;
  3703.  
  3704.   cmpltr = -1;
  3705.   if ( **s == ',' ) {
  3706.     *s+=1;
  3707.     name = *s;
  3708.     while ( **s != ',' && **s != ' ' && **s != '\t' )
  3709.       *s += 1;
  3710.     c = **s;
  3711.     **s = 0x00;
  3712.     if ( strcasecmp(name,"tr") == 0 ) {
  3713.       cmpltr = 0;
  3714.     }
  3715.     else if ( strcmp(name,"<>") == 0 ) {
  3716.       cmpltr = 1;
  3717.     }
  3718.     else if ( strcmp(name,">=") == 0 ) {
  3719.       cmpltr = 2;
  3720.     }
  3721.     else if ( strcmp(name,">") == 0 ) {
  3722.       cmpltr = 3;
  3723.     }
  3724.     else if ( strcmp(name,">>=") == 0 ) {
  3725.       cmpltr = 4;
  3726.     }
  3727.     else if ( strcmp(name,">>") == 0 ) {
  3728.       cmpltr = 5;
  3729.     }
  3730.     else if ( strcasecmp(name,"nsv") == 0 ) {
  3731.       cmpltr = 6;
  3732.     }
  3733.     else if ( strcasecmp(name,"ev") == 0 ) {
  3734.       cmpltr = 7;
  3735.     }
  3736.     **s = c;
  3737.   }
  3738.   if ( cmpltr >= 0 ) {
  3739.     while ( **s == ' ' || **s == '\t' )
  3740.       *s = *s + 1;
  3741.   }
  3742.  
  3743.   return cmpltr;
  3744. }
  3745.  
  3746. int pa_parse_nonneg_add_cmpltr(s)
  3747.      char **s;
  3748. {
  3749.   int cmpltr;
  3750.   char *name;
  3751.   char c;
  3752.  
  3753.   cmpltr = -1;
  3754.   if ( **s == ',' ) {
  3755.     *s+=1;
  3756.     name = *s;
  3757.     while ( **s != ',' && **s != ' ' && **s != '\t' )
  3758.       *s += 1;
  3759.     c = **s;
  3760.     **s = 0x00;
  3761.     if ( strcmp(name,"=") == 0 ) {
  3762.       cmpltr = 1;
  3763.     }
  3764.     else if ( strcmp(name,"<") == 0 ) {
  3765.       cmpltr = 2;
  3766.     }
  3767.     else if ( strcmp(name,"<=") == 0 ) {
  3768.       cmpltr = 3;
  3769.     }
  3770.     else if ( strcasecmp(name,"nuv") == 0 ) {
  3771.       cmpltr = 4;
  3772.     }
  3773.     else if ( strcasecmp(name,"znv") == 0 ) {
  3774.       cmpltr = 5;
  3775.     }
  3776.     else if ( strcasecmp(name,"sv") == 0 ) {
  3777.       cmpltr = 6;
  3778.     }
  3779.     else if ( strcasecmp(name,"od") == 0 ) {
  3780.       cmpltr = 7;
  3781.     }
  3782.     **s = c;
  3783.   }
  3784.   if ( cmpltr >= 0 ) {
  3785.     while ( **s == ' ' || **s == '\t' )
  3786.       *s = *s + 1;
  3787.   }
  3788.  
  3789.   return cmpltr;
  3790. }
  3791.  
  3792. int pa_parse_neg_add_cmpltr(s)
  3793.      char **s;
  3794. {
  3795.   int cmpltr;
  3796.   char *name;
  3797.   char c;
  3798.  
  3799.   cmpltr = -1;
  3800.   if ( **s == ',' ) {
  3801.     *s+=1;
  3802.     name = *s;
  3803.     while ( **s != ',' && **s != ' ' && **s != '\t' )
  3804.       *s += 1;
  3805.     c = **s;
  3806.     **s = 0x00;
  3807.     if ( strcasecmp(name,"tr") == 0 ) {
  3808.       cmpltr = 0;
  3809.     }
  3810.     else if ( strcmp(name,"<>") == 0 ) {
  3811.       cmpltr = 1;
  3812.     }
  3813.     else if ( strcmp(name,">=") == 0 ) {
  3814.       cmpltr = 2;
  3815.     }
  3816.     else if ( strcmp(name,">") == 0 ) {
  3817.       cmpltr = 3;
  3818.     }
  3819.     else if ( strcmp(name,"uv") == 0 ) {
  3820.       cmpltr = 4;
  3821.     }
  3822.     else if ( strcmp(name,"vnz") == 0 ) {
  3823.       cmpltr = 5;
  3824.     }
  3825.     else if ( strcasecmp(name,"nsv") == 0 ) {
  3826.       cmpltr = 6;
  3827.     }
  3828.     else if ( strcasecmp(name,"ev") == 0 ) {
  3829.       cmpltr = 7;
  3830.     }
  3831.     **s = c;
  3832.   }
  3833.   if ( cmpltr >= 0 ) {
  3834.     while ( **s == ' ' || **s == '\t' )
  3835.       *s = *s + 1;
  3836.   }
  3837.  
  3838.   return cmpltr;
  3839. }
  3840.  
  3841. void s_seg()
  3842. {
  3843.  
  3844.     if (strncmp(input_line_pointer, "\"text\"", 6) == 0) {
  3845.     input_line_pointer += 6;
  3846.     s_text();
  3847.     return;
  3848.     }
  3849.     if (strncmp(input_line_pointer, "\"data\"", 6) == 0) {
  3850.     input_line_pointer += 6;
  3851.     s_data();
  3852.     return;
  3853.     }
  3854.     if (strncmp(input_line_pointer, "\"data1\"", 7) == 0) {
  3855.     input_line_pointer += 7;
  3856.     s_data1();
  3857.     return;
  3858.     }
  3859.     as_bad("Unknown segment type");
  3860.     demand_empty_rest_of_line();
  3861.     return;
  3862. }
  3863.  
  3864. void s_private()
  3865. {
  3866.     register int temp;
  3867.  
  3868.     temp = get_absolute_expression ();
  3869. #ifdef OBJ_SOM
  3870.     subseg_new (SEG_DATA, (subsegT)temp);
  3871. #else
  3872.     subseg_new ("$PRIVATE$", (subsegT)temp);
  3873. #endif
  3874.     demand_empty_rest_of_line();
  3875. }
  3876.  
  3877. void s_data1()
  3878. {
  3879. #ifdef OBJ_SOM
  3880.     subseg_new(SEG_DATA, 1);
  3881. #else
  3882.     subseg_new("$PRIVATE$", 1);
  3883. #endif
  3884.     demand_empty_rest_of_line();
  3885.     return;
  3886. }
  3887.  
  3888. void s_proc()
  3889. {
  3890.     extern char is_end_of_line[];
  3891.  
  3892.     while (!is_end_of_line[*input_line_pointer]) {
  3893.     ++input_line_pointer;
  3894.     }
  3895.     ++input_line_pointer;
  3896.     return;
  3897. }
  3898.  
  3899. void pa_block(z)
  3900.      int z;
  3901. {
  3902.     register char *p;
  3903.     register long int temp_fill;
  3904.     register long int temp_size;
  3905.     register int i;
  3906.  
  3907.     temp_size = get_absolute_expression ();
  3908.  
  3909.     if (z) {                  /* fill with zeroes even if not requested to do so. */
  3910.       temp_fill = 0;          /* HP assembler does this too. */
  3911.     }
  3912.     else {
  3913.       temp_fill = 0;
  3914.     }
  3915.  
  3916.     if ( temp_size <= 0 ) {
  3917.       as_bad("size < 0, .block ignored");
  3918.       temp_size = 0;
  3919.     }
  3920.     p = frag_var(rs_fill,
  3921.          (int)temp_size,
  3922.          (int)temp_size,(relax_substateT)0,(symbolS *)0,1,(char *)0);
  3923.     bzero (p, (int)temp_size);
  3924.  
  3925.     /* convert 2 bytes at a time */
  3926.  
  3927.     for ( i = 0; i < temp_size; i+=2 ) {
  3928.       md_number_to_chars (p+i,
  3929.               temp_fill,
  3930.               (int)( (temp_size - i) > 2 ? 2 : (temp_size - i)));
  3931.     }
  3932.  
  3933.     demand_empty_rest_of_line();
  3934.     return;
  3935. }
  3936.  
  3937. void pa_call()
  3938. {
  3939.  
  3940.   pa_call_args(&last_call_desc);
  3941.   demand_empty_rest_of_line();
  3942.   return;
  3943. }
  3944.  
  3945. void pa_call_args(call_desc)
  3946.   register call_descS     *call_desc;
  3947. {
  3948.   register char *name;
  3949.   register char c;
  3950.   register char *p;
  3951.   register int temp;
  3952.   register unsigned int arg_reloc;
  3953.  
  3954.   while ( !is_end_of_statement() ) {
  3955.     name = input_line_pointer;
  3956.     c = get_symbol_end();
  3957.     if ( (strncasecmp(name, "argw", 4) == 0) ) {
  3958.       temp = atoi(name+4);
  3959.       p = input_line_pointer;
  3960.       *p = c;
  3961.       input_line_pointer++;
  3962.       name = input_line_pointer;
  3963.       c = get_symbol_end();
  3964.       arg_reloc = pa_build_arg_reloc(name);
  3965.       call_desc->arg_reloc |= pa_align_arg_reloc(temp,arg_reloc);
  3966.     }
  3967.     else if ( (strncasecmp(name, "rtnval", 6) == 0) ) {
  3968.       p = input_line_pointer;
  3969.       *p = c;
  3970.       input_line_pointer++;
  3971.       name = input_line_pointer;
  3972.       c = get_symbol_end();
  3973.       arg_reloc = pa_build_arg_reloc(name);
  3974.       call_desc->arg_reloc |= ( arg_reloc & 0x3 );
  3975.     }
  3976.     else {
  3977.       as_bad("Unrecognized .CALL argument: %s",name);
  3978.     }
  3979.     p = input_line_pointer;
  3980.     *p = c;
  3981.     if ( !is_end_of_statement() )
  3982.       input_line_pointer++;
  3983.   }
  3984. }
  3985.  
  3986. static int
  3987. is_same_frag(frag1P,frag2P)
  3988.      fragS *frag1P;
  3989.      fragS *frag2P;
  3990. {
  3991.  
  3992.   if ( frag1P == NULL )
  3993.     return (FALSE);
  3994.   else if ( frag2P == NULL )
  3995.     return (FALSE);
  3996.   else if ( frag1P == frag2P )
  3997.     return (TRUE);
  3998.   else if ( frag2P->fr_type == rs_fill && frag2P->fr_fix == 0 )
  3999.     is_same_frag(frag1P,frag2P->fr_next);
  4000.   else
  4001.     return (FALSE);
  4002. }
  4003.  
  4004. #ifdef OBJ_ELF
  4005. static void
  4006. pa_build_unwind_subspace(call_info)
  4007.      call_infoS *call_info;
  4008. {
  4009.   char *unwindP;
  4010.   asection *seg;
  4011.   asection *save_seg;
  4012.   subsegT subseg,save_subseg;
  4013.   int i;
  4014.   char c;
  4015.   char *p;
  4016.  
  4017.   subseg = SUBSEG_UNWIND;
  4018.   seg = bfd_get_section_by_name(stdoutput,UNWIND_SECTION_NAME);
  4019.   if ( seg == ASEC_NULL ) {
  4020.       seg = bfd_make_section_old_way(stdoutput,UNWIND_SECTION_NAME);
  4021.       bfd_set_section_flags (stdoutput,
  4022.                  seg,
  4023.                  SEC_READONLY | SEC_ALLOC | SEC_LOAD | SEC_RELOC);
  4024.   }
  4025.  
  4026.   /* callinfo.frame is in bytes and unwind_desc is in 8 byte units */
  4027.   call_info->ci_unwind.descriptor.frame_size = call_info->frame / 8;
  4028.  
  4029.   /* Now, dump the unwind descriptor to the $UNWIND$ subspace. This
  4030.      creates a couple of relocations */
  4031.  
  4032.   save_seg = now_seg;
  4033.   save_subseg = now_subseg;
  4034.   subseg_new((char *)seg->name,subseg);
  4035.   unwindP = (char *)&call_info->ci_unwind;
  4036.  
  4037.   p = frag_more(4);
  4038.   call_info->start_offset_frag = frag_now;
  4039.   call_info->start_frag_where = p - frag_now->fr_literal;
  4040.  
  4041.   /* relocation info. for start offset of the function */
  4042.  
  4043.   fix_new_hppa (frag_now, p - frag_now -> fr_literal, 4,
  4044.         call_info->start_symbol, (symbolS *) NULL,
  4045.         0, 0, R_HPPA, e_fsel, 32, 0, (char *) 0);
  4046.  
  4047.   /** we need to search for the first relocation involving the start_symbol of **/
  4048.   /** this call_info descriptor **/
  4049.  
  4050.   {
  4051.     fixS *fixP;
  4052.  
  4053.     call_info->start_fix = seg_info(now_seg)->fix_root;   /* the default */
  4054.     for ( fixP = call_info->start_fix; fixP; fixP = fixP->fx_next ) {
  4055.         if ( fixP->fx_addsy == call_info->start_symbol
  4056.         || fixP->fx_subsy == call_info->start_symbol ) {
  4057.             call_info->start_fix = fixP;
  4058.             break;
  4059.         }
  4060.     }
  4061.   }     
  4062.  
  4063.   p = frag_more(4);
  4064.   call_info->end_offset_frag = frag_now;
  4065.   call_info->end_frag_where = p - frag_now->fr_literal;
  4066.  
  4067.   /* relocation info. for end offset of the function */
  4068.  
  4069.     fix_new_hppa (frag_now, p - frag_now -> fr_literal, 4,
  4070.           call_info->end_symbol, (symbolS *) NULL,
  4071.           0, 0, R_HPPA, e_fsel, 32, 0, (char *) 0);
  4072.  
  4073.   /** we need to search for the first relocation involving the start_symbol of **/
  4074.   /** this call_info descriptor **/
  4075.  
  4076.   {
  4077.     fixS *fixP;
  4078.  
  4079.     call_info->end_fix = seg_info(now_seg)->fix_root;   /* the default */
  4080.     for ( fixP = call_info->end_fix; fixP; fixP = fixP->fx_next ) {
  4081.         if ( fixP->fx_addsy == call_info->end_symbol
  4082.         || fixP->fx_subsy == call_info->end_symbol ) {
  4083.             call_info->end_fix = fixP;
  4084.             break;
  4085.         }
  4086.     }
  4087.   }
  4088.  
  4089.   for ( i = 8; i < sizeof(unwind_tableS); i++ ) {
  4090.     c = *(unwindP + i);
  4091.     {
  4092.       FRAG_APPEND_1_CHAR( c );
  4093.     }
  4094.   }
  4095.  
  4096.     subseg_new((char *)save_seg->name,save_subseg);
  4097. }
  4098. #else
  4099. #ifdef OBJ_SOM
  4100. static void
  4101. pa_build_unwind_subspace(call_info)
  4102.      call_infoS *call_info;
  4103. {
  4104.   space_dict_chainS *spaceP;
  4105.   subspace_dict_chainS *subspaceP;
  4106.   char *unwindP;
  4107.   char defined,loadable,code_only,common,dup_common,is_zero,sort;
  4108.   int access,space_index,alignment,quadrant;
  4109.   segT seg,save_seg;
  4110.   subsegT subseg,save_subseg;
  4111.   int i;
  4112.   char c;
  4113.   char *p;
  4114.  
  4115.   defined = 1;
  4116.   loadable = 1;
  4117.   code_only = 0;
  4118.   common = 0;
  4119.   dup_common = 0;
  4120.   is_zero = 0;
  4121.   sort = 0x40;
  4122.   access = 0x2c;
  4123.   space_index = 0;
  4124.   alignment = 8;
  4125.   quadrant = 0;
  4126.   subseg = SUBSEG_UNWIND;
  4127.   seg = SEG_TEXT;
  4128.  
  4129.   spaceP = pa_segment_to_space(seg);
  4130.  
  4131.   if ( (subspaceP = is_defined_subspace("$UNWIND$",SUBSEG_UNWIND) ) ) {
  4132.     update_subspace("$UNWIND$",defined,loadable,code_only,common,dup_common,
  4133.             sort,is_zero,access,space_index,alignment,quadrant,
  4134.             SUBSEG_UNWIND);
  4135.   }
  4136.   else {
  4137.     subspaceP = create_new_subspace(spaceP,"$UNWIND$",defined,loadable,code_only,
  4138.                     common,dup_common,is_zero,sort,access,
  4139.                     space_index,alignment,quadrant,seg);
  4140.   }
  4141.  
  4142.  
  4143.   /* callinfo.frame is in bytes and unwind_desc is in 8 byte units */
  4144.   call_info->ci_unwind.descriptor.frame_size = call_info->frame / 8;
  4145.  
  4146.   /* Now, dump the unwind descriptor to the $UNWIND$ subspace. This
  4147.      creates a couple of relocations */
  4148.  
  4149.   save_seg = now_seg;
  4150.   save_subseg = now_subseg;
  4151.   subseg_new(seg,subseg);
  4152.   unwindP = (char *)&call_info->ci_unwind;
  4153.  
  4154.   p = frag_more(4);
  4155.   call_info->start_offset_frag = frag_now;
  4156.   call_info->start_frag_where = p - frag_now->fr_literal;
  4157.  
  4158.   /* relocation info. for start offset of the function */
  4159.  
  4160.   fix_new (frag_now, p - frag_now -> fr_literal, 4,
  4161.        call_info->start_symbol, (symbolS *) NULL,
  4162.        0, 0, R_DATA_ONE_SYMBOL, e_fsel, 0, 0, (char *) 0);
  4163.  
  4164.   /** we need to search for the first relocation involving the start_symbol of **/
  4165.   /** this call_info descriptor **/
  4166.  
  4167.   {
  4168.     fixS *fixP;
  4169.  
  4170.     call_info->start_fix = seg_info(now_seg)->fix_root;   /* the default */
  4171.     for ( fixP = call_info->start_fix; fixP; fixP = fixP->fx_next ) {
  4172.       /*
  4173.       if ( ( fixP->fx_addsy == call_info->start_symbol ||
  4174.          fixP->fx_subsy == call_info->start_symbol )
  4175.       &&
  4176.        ( fixP->fx_frag == call_info->start_symbol->sy_frag ) ) {
  4177.        */
  4178.       if ( ( fixP->fx_addsy == call_info->start_symbol ||
  4179.          fixP->fx_subsy == call_info->start_symbol )
  4180.       &&
  4181.        ( is_same_frag(fixP->fx_frag,call_info->start_symbol->sy_frag) ) ) {
  4182.     call_info->start_fix = fixP;
  4183.     break;
  4184.       }
  4185.     }
  4186.   }     
  4187.  
  4188.   p = frag_more(4);
  4189.   call_info->end_offset_frag = frag_now;
  4190.   call_info->end_frag_where = p - frag_now->fr_literal;
  4191.  
  4192.   /* relocation info. for end offset of the function */
  4193.  
  4194.     fix_new (frag_now, p - frag_now -> fr_literal, 4,
  4195.          call_info->start_symbol, (symbolS *) NULL,
  4196.          0, 0, R_DATA_ONE_SYMBOL, e_fsel, 0, 0, (char *) 0);
  4197.  
  4198.   /** we need to search for the first relocation involving the start_symbol of **/
  4199.   /** this call_info descriptor **/
  4200.  
  4201.   {
  4202.     fixS *fixP;
  4203.  
  4204.     call_info->end_fix = seg_info(now_seg)->fix_root;   /* the default */
  4205.     for ( fixP = call_info->end_fix; fixP; fixP = fixP->fx_next ) {
  4206.       /*
  4207.       if ( ( fixP->fx_addsy == call_info->start_symbol ||
  4208.          fixP->fx_subsy == call_info->start_symbol )
  4209.       &&
  4210.        ( fixP->fx_frag == call_info->start_symbol->sy_frag ) ) {
  4211.        */
  4212.       if ( ( fixP->fx_addsy == call_info->start_symbol ||
  4213.          fixP->fx_subsy == call_info->start_symbol )
  4214.       &&
  4215.        ( is_same_frag(fixP->fx_frag,call_info->start_symbol->sy_frag) ) ) {
  4216.     call_info->end_fix = fixP;
  4217.     break;
  4218.       }
  4219.     }
  4220.   }
  4221.  
  4222.   for ( i = 8; i < sizeof(unwind_tableS); i++ ) {
  4223.     c = *(unwindP + i);
  4224.     {
  4225.       FRAG_APPEND_1_CHAR( c );
  4226.     }
  4227.   }
  4228.  
  4229.     subseg_new(save_seg,save_subseg);
  4230.  
  4231. }
  4232. #endif
  4233. #endif
  4234.  
  4235. void pa_callinfo()
  4236. {
  4237.     register char *name;
  4238.     register char c;
  4239.     register char *p;
  4240.     register int temp;
  4241.     register symbolS *    symbolP;
  4242.  
  4243.     if ( !within_procedure )
  4244.       as_bad(".callinfo is not within a procedure definition");
  4245.  
  4246.     callinfo_found = TRUE;
  4247.  
  4248.     while ( !is_end_of_statement() ) {
  4249.       name = input_line_pointer;
  4250.       c = get_symbol_end();
  4251.       if ( (strncasecmp(name, "frame", 5) == 0) ) {
  4252.     p = input_line_pointer;
  4253.     *p = c;
  4254.     input_line_pointer++;
  4255.     temp = get_absolute_expression ();
  4256.     if ( ( temp & 0x3 ) != 0 ) {
  4257.       as_bad("FRAME parameter must be a multiple of 8: %d\n",temp);
  4258.       temp = 0;
  4259.     }
  4260.     last_call_info->frame = temp;
  4261.       }
  4262.       else if ( (strncasecmp(name, "entry_gr", 8) == 0) ) {
  4263.     p = input_line_pointer;
  4264.     *p = c;
  4265.     input_line_pointer++;
  4266.     temp = get_absolute_expression ();
  4267.     last_call_info->ci_unwind.descriptor.entry_gr = temp;
  4268.       }
  4269.       else if ( (strncasecmp(name, "entry_fr", 8) == 0) ) {
  4270.     p = input_line_pointer;
  4271.     *p = c;
  4272.     input_line_pointer++;
  4273.     temp = get_absolute_expression ();
  4274.     last_call_info->ci_unwind.descriptor.entry_fr = temp;
  4275.       }
  4276.       else if ( (strncasecmp(name, "entry_sr", 8) == 0) ) {
  4277.     p = input_line_pointer;
  4278.     *p = c;
  4279.     input_line_pointer++;
  4280.     temp = get_absolute_expression ();
  4281.     last_call_info->entry_sr = temp;
  4282.       }
  4283.       else if ( (strncasecmp(name, "calls", 5) == 0) ||
  4284.             (strncasecmp(name, "caller", 6) == 0) ) {
  4285.     p = input_line_pointer;
  4286.     *p = c;
  4287.     last_call_info->makes_calls = 1;
  4288.       }
  4289.       else if ( (strncasecmp(name, "no_calls", 8) == 0) ) {
  4290.     p = input_line_pointer;
  4291.     *p = c;
  4292.     last_call_info->makes_calls = 0;
  4293.       }
  4294.       else if ( (strncasecmp(name, "save_rp",7) == 0) ) {
  4295.     p = input_line_pointer;
  4296.     *p = c;
  4297.     last_call_info->ci_unwind.descriptor.save_rp = 1;
  4298.       }
  4299.       else if ( (strncasecmp(name, "save_sp",7) == 0) ) {
  4300.     p = input_line_pointer;
  4301.     *p = c;
  4302.     last_call_info->ci_unwind.descriptor.save_sp = 1;
  4303.       }
  4304.       else if ( (strncasecmp(name, "no_unwind",9) == 0) ) {
  4305.     p = input_line_pointer;
  4306.     *p = c;
  4307.     last_call_info->ci_unwind.descriptor.cannot_unwind = 1;
  4308.       }
  4309.       else if ( (strncasecmp(name, "hpux_int",7) == 0) ) {
  4310.     p = input_line_pointer;
  4311.     *p = c;
  4312.     last_call_info->hpux_int = 1;
  4313.       }
  4314.       else {
  4315.     as_bad("Unrecognized .CALLINFO argument: %s",name);
  4316.       }
  4317.       if (  !is_end_of_statement() )
  4318.     input_line_pointer++;
  4319.     }
  4320.  
  4321.     demand_empty_rest_of_line();
  4322.     return;
  4323. }
  4324.  
  4325. void pa_code()
  4326. {
  4327.   space_dict_chainS *sdchain;
  4328.  
  4329.   if ( (sdchain = is_defined_space("$TEXT$")) == NULL ) {
  4330.     sdchain = create_new_space(pa_def_spaces[0].name,pa_def_spaces[0].spnum,
  4331.                    pa_def_spaces[0].loadable,pa_def_spaces[0].defined,
  4332.                    pa_def_spaces[0].private,pa_def_spaces[0].sort,
  4333.                    1,pa_def_spaces[0].segment);
  4334.   }
  4335.  
  4336.   SPACE_DEFINED(sdchain) = 1;
  4337. #ifdef OBJ_SOM
  4338.  
  4339.   subseg_new (SEG_TEXT, SUBSEG_CODE);
  4340. #else
  4341.  
  4342.   subseg_new (".text",SUBSEG_CODE);
  4343. #endif
  4344.       
  4345.   demand_empty_rest_of_line();
  4346.   return;
  4347. }
  4348.  
  4349. /*
  4350.  * This is different than the standard GAS s_comm(). On HP9000/800 machines,
  4351.  * the .comm pseudo-op has the following symtax:
  4352.  *
  4353.  *     <label> .comm <length>
  4354.  *
  4355.  * where <label> is optional and is a symbol whose address will be the start of
  4356.  * a block of memory <length> bytes long. <length> must be an absolute expressio
  4357. n.
  4358.  * <length> bytes will be allocated in the current space and subspace.
  4359.  *
  4360.  */
  4361.  
  4362. void
  4363. pa_comm()
  4364. {
  4365.   register char *p;
  4366.   register int size,i;
  4367.   register symbolS *symbolP;
  4368.   register label_symbolS *label_symbolP = pa_get_label();
  4369.  
  4370.   if ( label_symbolP )
  4371.     symbolP = label_symbolP->lss_label;
  4372.   else
  4373.     symbolP = NULL;
  4374.   
  4375.   SKIP_WHITESPACE();
  4376.   if ( (size = get_absolute_expression ()) < 0 ) {
  4377.     as_warn(".COMMon length (%d.) <0! Ignored.", size);
  4378.     ignore_rest_of_line();
  4379.     return;
  4380.   }
  4381.  
  4382.   if ( symbolP ) {
  4383. #ifdef OBJ_SOM
  4384.       if ( symbolP -> pa_sy_type == ST_STORAGE &&
  4385.           symbolP -> pa_sy_scope == SS_UNSAT ) {
  4386.           if (symbolP -> pa_sy_value != size) {
  4387.               as_warn( "Length of .comm \"%s\" is already %d. Not changed to %d.",
  4388.                   symbolP -> pa_sy_name, symbolP -> pa_sy_value, size);
  4389.               return;
  4390.           }
  4391.       }
  4392.       else {
  4393.           symbolP -> pa_sy_value = size;
  4394.           symbolP -> pa_sy_scope = SS_UNSAT;
  4395.           symbolP -> pa_sy_type  = ST_STORAGE;
  4396.           symbolP -> sy_ref      = sym_def;
  4397.       }
  4398. #endif
  4399. #ifdef OBJ_ELF
  4400.       if ( S_IS_DEFINED(symbolP) && S_GET_SEGMENT(symbolP) == bss_section ) {
  4401.         as_bad("Ignoring attempt to re-define symbol");
  4402.         ignore_rest_of_line();
  4403.         return;
  4404.       }
  4405.       if ( S_GET_VALUE(symbolP) ) {
  4406.           if ( S_GET_VALUE(symbolP) != size) {
  4407.               as_warn( "Length of .comm \"%s\" is already %d. Not changed to %d.",
  4408.                   S_GET_NAME(symbolP), S_GET_VALUE(symbolP), size);
  4409.               return;
  4410.           }
  4411.       }
  4412.       else {
  4413.           S_SET_VALUE(symbolP, size);
  4414.           S_SET_SEGMENT(symbolP,bss_section);
  4415.           S_SET_EXTERNAL(symbolP);
  4416.       }
  4417. #endif
  4418.   }
  4419.  
  4420.  
  4421.   demand_empty_rest_of_line();
  4422. }
  4423.  
  4424. void pa_copyright()
  4425. {
  4426.     register char *name;
  4427.     register char c;
  4428.     register char *p;
  4429.     register int temp;
  4430.     register symbolS *    symbolP;
  4431.  
  4432.     SKIP_WHITESPACE();
  4433.     if (* input_line_pointer == '\"') {
  4434.       ++ input_line_pointer; /* -> 1st char of string. */
  4435.       name = input_line_pointer;
  4436.       while ( (c = next_char_of_string()) >= 0)
  4437.     ;
  4438.       c = *input_line_pointer;
  4439.       *input_line_pointer = '\0';
  4440.       *(input_line_pointer-1) = '\0';
  4441.       {
  4442. #ifdef OBJ_SOM
  4443. #define PREFIX    "Copyright "
  4444. #define MIDFIX  ". All rights reserved. No part of this program may be photocopied, reproduced, or transmitted without prior written consent of "
  4445. #define SUFFIX "."
  4446.  
  4447.     struct aux_hdr_list *aux_hdr_entry;
  4448.     int len;
  4449.     char *company_name = name;
  4450.     char *date_part;
  4451.  
  4452.     date_part = (char *) index (name,',');
  4453.     if ( date_part ) {
  4454.       *date_part = 0x00;
  4455.       date_part++;
  4456.     }
  4457.  
  4458.     len =
  4459.       strlen(PREFIX) +
  4460.         strlen(MIDFIX) +
  4461.           strlen(SUFFIX) +
  4462.         2*strlen(name);
  4463.  
  4464.     if ( date_part ) {
  4465.       len += strlen(date_part) + strlen(",");
  4466.     }
  4467.  
  4468.     aux_hdr_entry =(struct aux_hdr_list *)malloc(sizeof(struct aux_hdr_list));
  4469.     if ( aux_hdr_root ) {
  4470.       aux_hdr_entry->ahl_next = aux_hdr_root;
  4471.       aux_hdr_root = aux_hdr_entry;
  4472.     }
  4473.     else {
  4474.       aux_hdr_entry->ahl_next = NULL;
  4475.       aux_hdr_root = aux_hdr_entry;
  4476.     }
  4477.     aux_hdr_entry->type = COPYRIGHT_AUX_ID;
  4478.     aux_hdr_entry->contents.cpy.header_id.append = 1;
  4479.     aux_hdr_entry->contents.cpy.header_id.type = COPYRIGHT_AUX_ID;
  4480.     aux_hdr_entry->contents.cpy.header_id.length = len + sizeof(unsigned int);
  4481.     while ( aux_hdr_entry->contents.usr_str.header_id.length % 4 )
  4482.       aux_hdr_entry->contents.usr_str.header_id.length += 1;
  4483.  
  4484.     aux_hdr_entry->contents.cpy.string_length = len;
  4485.     aux_hdr_entry->contents.cpy.copyright = (char *)(malloc(len + 1));
  4486.     strcpy(aux_hdr_entry->contents.cpy.copyright,PREFIX);
  4487.     strcat(aux_hdr_entry->contents.cpy.copyright,name);
  4488.     if ( date_part ) {
  4489.       strcat(aux_hdr_entry->contents.cpy.copyright,",");
  4490.       strcat(aux_hdr_entry->contents.cpy.copyright,date_part);
  4491.     }
  4492.     strcat(aux_hdr_entry->contents.cpy.copyright,MIDFIX);
  4493.     strcat(aux_hdr_entry->contents.cpy.copyright,name);
  4494.     strcat(aux_hdr_entry->contents.cpy.copyright,SUFFIX);
  4495.     aux_hdr_entry->contents.cpy.copyright[len] = NULL;
  4496. #undef PREFIX
  4497. #undef MIDFIX
  4498. #undef SUFFIX
  4499. #endif /* OBJ_SOM */
  4500.       }
  4501.       *input_line_pointer = c;
  4502.     }
  4503.     else {
  4504.       as_bad( "Expected \"-ed string" );
  4505.     }
  4506.     demand_empty_rest_of_line();
  4507. }
  4508.  
  4509. void pa_end()
  4510. {
  4511.  
  4512.     demand_empty_rest_of_line();
  4513.     return;
  4514. }
  4515.  
  4516. void pa_enter()
  4517. {
  4518.  
  4519.   as_bad(".ENTER encountered. gas doesn't generate entry code sequences.");
  4520.   pa_entry();
  4521.   return;
  4522. }
  4523.  
  4524. void pa_entry()
  4525. {
  4526.   char *where;
  4527.  
  4528.   if ( !within_procedure )
  4529.     as_bad("Misplaced .entry. Ignored.");
  4530.   else {
  4531.     if ( !callinfo_found )
  4532.       as_bad("Missing .callinfo.");
  4533.  
  4534.     last_call_info->start_frag = frag_now;
  4535.   }
  4536.   demand_empty_rest_of_line();
  4537.   within_entry_exit = TRUE;
  4538.   where = frag_more(0);
  4539. #ifdef OBJ_SOM
  4540.   fix_new (frag_now, where - frag_now->fr_literal, 0,
  4541.        last_call_info->start_symbol, (symbolS *) NULL, 0, 0,
  4542.        R_ENTRY, e_fsel, 0, 0, (char *) &last_call_info->ci_unwind.descriptor);
  4543. #else
  4544. #ifdef OBJ_ELF
  4545.   /* XXX: no ENTRY relocation for PA ELF.  What do we do instead? */
  4546. #else
  4547.   fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
  4548.         last_call_info->start_symbol, (symbolS *) NULL, 0, 0,
  4549.         R_HPPA_ENTRY, 0, 0, 0,
  4550.         (char *) &last_call_info->ci_unwind.descriptor);
  4551. #endif
  4552. #endif
  4553.   return;
  4554. }
  4555.  
  4556. void pa_equ(reg)
  4557.      int reg;
  4558. {
  4559.     register label_symbolS *label_symbolP = pa_get_label();
  4560.     register symbolS *    symbolP;
  4561.  
  4562.     if ( label_symbolP ) {
  4563.         symbolP = label_symbolP->lss_label;
  4564. #ifdef OBJ_SOM
  4565.         symbolP->pa_sy_value = get_absolute_expression();
  4566.         symbolP->pa_sy_type = ST_ABSOLUTE;
  4567.         symbolP->sy_ref = sym_unref;
  4568.         symbolP->sy_equ = 1;
  4569. #else
  4570.         S_SET_VALUE(symbolP,get_absolute_expression());
  4571.         S_SET_SEGMENT(symbolP,&bfd_abs_section);
  4572. #endif
  4573.     }
  4574.     else {
  4575.       if ( reg )
  4576.     as_bad(".REG must use a label");
  4577.       else
  4578.     as_bad(".EQU must use a label");
  4579.     }
  4580.  
  4581.     demand_empty_rest_of_line();
  4582.     return;
  4583. }
  4584.  
  4585. void process_exit()
  4586. {
  4587.   char *where;
  4588.  
  4589.   where = frag_more(0);
  4590. #ifdef OBJ_SOM
  4591.   fix_new (frag_now, where - frag_now->fr_literal, 0,
  4592.        last_call_info->start_symbol, (symbolS *) NULL, 0,
  4593.        0, R_EXIT, e_fsel, 0, 0, (char *) NULL);
  4594. #endif
  4595. #ifdef OBJ_ELF
  4596.   /* XXX: no EXIT relocation for PA ELF.  All we do is create a */
  4597.   /* temporary symbol marking the end of the function. */
  4598.   {
  4599.       char *name = (char *)xmalloc(strlen("L\001end_") +
  4600.                        strlen(S_GET_NAME(last_call_info->start_symbol)) + 1);
  4601.  
  4602.       if ( name ) {
  4603.           symbolS *symbolP;
  4604.  
  4605.           strcpy(name,"L\001end_");
  4606.           strcat(name,S_GET_NAME(last_call_info->start_symbol));
  4607.           
  4608.           symbolP = symbol_find (name);
  4609.           if ( symbolP )
  4610.               as_warn("Symbol '%s' already defined.", name);
  4611.           else {
  4612.               /* symbol value should be the offset of the */
  4613.               /* last instruction of the function */
  4614.               symbolP = symbol_new(name,
  4615.                            now_seg, 
  4616.                            (valueT)(obstack_next_free(&frags)-frag_now->fr_literal-4),
  4617.                            frag_now);
  4618.  
  4619.               assert(symbolP);
  4620.  
  4621.               symbolP->bsym->flags = last_call_info->start_symbol->bsym->flags;
  4622.               symbol_table_insert(symbolP);
  4623.           }
  4624.           if ( symbolP )
  4625.               last_call_info->end_symbol = symbolP;
  4626.           else
  4627.               as_bad("Symbol '%s' could not be created.", name);
  4628.          
  4629.       }
  4630.       else
  4631.           as_bad("No memory for symbol name.");
  4632.   }
  4633. #else
  4634.   fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
  4635.         last_call_info->start_symbol, (symbolS *) NULL, 0,
  4636.         0, R_HPPA_EXIT, 0, 0, 0, (char *) NULL);
  4637. #endif
  4638.   last_call_info->end_frag = frag_now;
  4639.  
  4640.   pa_build_unwind_subspace(last_call_info);
  4641.  
  4642.   exit_processing_complete = TRUE;
  4643. }
  4644.  
  4645. void pa_exit()
  4646. {
  4647.  
  4648.   if ( !within_procedure )
  4649.     as_bad(".EXIT must appear within a procedure");
  4650.   else {
  4651.     if ( !callinfo_found )
  4652.       as_bad("Missing .callinfo");
  4653.     else {
  4654.       if ( !within_entry_exit )
  4655.     as_bad("No .ENTRY for this .EXIT");
  4656.       else {
  4657.     within_entry_exit = FALSE;
  4658.     process_exit();
  4659.       }
  4660.     }
  4661.   }
  4662.   demand_empty_rest_of_line();
  4663.   return;
  4664. }
  4665.  
  4666. void pa_export()
  4667. {
  4668.     register char *name;
  4669.     register char c;
  4670.     register char *p;
  4671.     register int temp;
  4672.     register int regno;
  4673.     register symbolS *    symbolP;
  4674.  
  4675.     name = input_line_pointer;
  4676.     c = get_symbol_end();
  4677.     /* just after name is now '\0' */
  4678.  
  4679.     if ( (symbolP = symbol_find_or_make(name)) == NULL ) {
  4680.       as_bad("Cannot define export symbol: %s\n",name);
  4681.       p = input_line_pointer;
  4682.       *p = c;
  4683.       input_line_pointer++;
  4684.     }
  4685.     else {
  4686. #ifdef OBJ_SOM
  4687.       symbolP->pa_sy_dict.symbol_scope = SS_UNIVERSAL;
  4688.       /* determination of the symbol_type field will have to wait until
  4689.      we know the subspace index (within the object file) of the subspace
  4690.      containing this symbol */
  4691. #else
  4692.       /* S_SET_SEGMENT(symbolP,&bfd_und_section); */
  4693.       S_SET_EXTERNAL(symbolP);
  4694.       /* symbolP->sy_frag = frag_now; */
  4695. #endif
  4696.  
  4697.       p = input_line_pointer;
  4698.       *p = c;
  4699.       if ( !is_end_of_statement() ) {
  4700.     input_line_pointer++;
  4701.     pa_export_args(symbolP);
  4702.       }
  4703.     }
  4704.  
  4705.     demand_empty_rest_of_line();
  4706.     return;
  4707. }
  4708.  
  4709. void pa_export_args(symbolP)
  4710.     register symbolS      *symbolP;
  4711. {
  4712.     register char *name;
  4713.     register char c;
  4714.     register char *p;
  4715.     register int temp;
  4716.  
  4717.     if (strncasecmp(input_line_pointer, "absolute", 8) == 0) {
  4718.       input_line_pointer += 8;
  4719. #ifdef OBJ_SOM
  4720.       symbolP->pa_sy_dict.symbol_type = ST_ABSOLUTE;
  4721. #else
  4722.       S_SET_SEGMENT(symbolP,&bfd_abs_section);
  4723. #endif
  4724.     }
  4725.     else if (strncasecmp(input_line_pointer, "code", 4) == 0) {
  4726.       input_line_pointer += 4;
  4727. #ifdef OBJ_SOM
  4728.       symbolP->pa_sy_dict.symbol_type = ST_CODE;
  4729. #else
  4730.       /* S_SET_SEGMENT(symbolP,text_section); */
  4731. #endif
  4732.     }
  4733.     else if (strncasecmp(input_line_pointer, "data", 4) == 0) {
  4734.       input_line_pointer += 4;
  4735. #ifdef OBJ_SOM
  4736.       symbolP->pa_sy_dict.symbol_type = ST_DATA;
  4737. #else
  4738.       /* S_SET_SEGMENT(symbolP,data_section); */
  4739. #endif
  4740.     }
  4741.     else if ( (strncasecmp(input_line_pointer, "entry", 5) == 0) ) {
  4742.       input_line_pointer += 5;
  4743. #ifdef OBJ_SOM
  4744.       symbolP->pa_sy_dict.symbol_type = ST_ENTRY;
  4745. #else
  4746.       symbolP->bsym->flags |= BSF_FUNCTION;
  4747. #endif
  4748.     }
  4749.     else if (strncasecmp(input_line_pointer, "millicode", 9) == 0) {
  4750.       input_line_pointer += 9;
  4751. #ifdef OBJ_SOM
  4752.       symbolP->pa_sy_dict.symbol_type = ST_MILLICODE;
  4753. #endif
  4754.     }
  4755.     else if (strncasecmp(input_line_pointer, "plabel", 6) == 0) {
  4756.       input_line_pointer += 6;
  4757. #ifdef OBJ_SOM
  4758.       symbolP->pa_sy_dict.symbol_type = ST_PLABEL;
  4759. #endif
  4760.     }
  4761.     else if (strncasecmp(input_line_pointer, "pri_prog", 8) == 0) {
  4762.       input_line_pointer += 8;
  4763. #ifdef OBJ_SOM
  4764.       symbolP->pa_sy_dict.symbol_type = ST_PRI_PROG;
  4765. #endif
  4766.     }
  4767.     else if (strncasecmp(input_line_pointer, "sec_prog", 8) == 0) {
  4768.       input_line_pointer += 8;
  4769. #ifdef OBJ_SOM
  4770.       symbolP->pa_sy_dict.symbol_type = ST_SEC_PROG;
  4771. #endif
  4772.     }
  4773.  
  4774.     while ( !is_end_of_statement() ) {
  4775.       if ( *input_line_pointer == ',' )
  4776.           input_line_pointer++;
  4777.       name = input_line_pointer;
  4778.       c = get_symbol_end();
  4779.       if ( (strncasecmp(name, "argw", 4) == 0) ) {
  4780.     p = input_line_pointer;
  4781.     *p = c;
  4782.     input_line_pointer++;
  4783.     temp = atoi(name+4);
  4784.     name = input_line_pointer;
  4785.     c = get_symbol_end();
  4786. #ifdef OBJ_SOM
  4787.     symbolP->pa_sy_dict.arg_reloc |=
  4788.                  pa_align_arg_reloc(temp,pa_build_arg_reloc(name));
  4789. #endif
  4790.     *input_line_pointer = c;
  4791.       }
  4792.       else if (( strncasecmp(name, "rtnval",6)) == 0 ) {
  4793.     p = input_line_pointer;
  4794.     *p = c;
  4795.     input_line_pointer++;
  4796.     name = input_line_pointer;
  4797.     c = get_symbol_end();
  4798. #ifdef OBJ_SOM
  4799.     symbolP->pa_sy_dict.arg_reloc |= pa_build_arg_reloc(name);
  4800. #endif
  4801.     *input_line_pointer = c;
  4802.       }
  4803.       else if (( strncasecmp(name, "priv_lev",8)) == 0 ) {
  4804.     p = input_line_pointer;
  4805.     *p = c;
  4806.     input_line_pointer++;
  4807.     /*** temp = get_absolute_expression (); ***/
  4808.     temp = atoi(input_line_pointer);
  4809.     c = get_symbol_end();
  4810.     *input_line_pointer = c;
  4811. #ifdef OBJ_SOM
  4812.     symbolP->sy_priv_lev = temp & 3;  /* this is stored in symbol_value later */
  4813. #endif
  4814.       }
  4815.       else {
  4816.     as_bad("Undefined .EXPORT/.IMPORT argument (ignored): %s",name);
  4817.     p = input_line_pointer;
  4818.     *p = c;
  4819.       }
  4820.       if ( !is_end_of_statement() )
  4821.     input_line_pointer++;
  4822.     }
  4823. }
  4824.  
  4825. void pa_import()
  4826. {
  4827.     register char *name;
  4828.     register char c;
  4829.     register char *p;
  4830.     register symbolS *symbolP;
  4831.     register expressionS resultP; /* Deliver result here. */
  4832.  
  4833.     name = input_line_pointer;
  4834.     c = get_symbol_end();
  4835.     /* just after name is now '\0' */
  4836.  
  4837.     symbolP = symbol_find_or_make (name);
  4838. #if defined(OBJ_ELF)
  4839.     /* symbolP->bsym->flags |= BSF_IMPORT; */ /* XXX BSF_IMPORT is obsolete */
  4840. #else
  4841.     /* Check to see if this symbol has already been exported (this means its */
  4842.     /* defined locally and the import statement is redundant). */
  4843.     /* If it has not been exported, go ahead and mark this symbol as SS_UNSAT */
  4844.     /* (an unsatisfied external symbol) */
  4845.  
  4846.     /* But, if the symbol has already been referenced (sy_ref == TRUE),
  4847.        leave it alone. */
  4848.  
  4849.     if ( !symbolP->sy_ref ) {
  4850.       if ( symbolP->pa_sy_dict.symbol_scope != SS_UNIVERSAL ) {
  4851.     symbolP->pa_sy_dict.symbol_scope = SS_UNSAT;
  4852.     symbolP->sy_ref = FALSE;
  4853.       }
  4854.     }
  4855. #endif
  4856.  
  4857.     p = input_line_pointer;
  4858.     *p = c;
  4859.  
  4860.     if ( !is_end_of_statement() ) {
  4861.        input_line_pointer++;
  4862.  
  4863.        pa_export_args(symbolP);
  4864. #ifdef OBJ_ELF
  4865.        /* In ELF, since this is an import, leave the section undefined.    */
  4866.        /* S_SET_SEGMENT(symbolP,&bfd_und_section); */
  4867. #endif
  4868.     }
  4869.     else {
  4870. #ifdef OBJ_SOM
  4871.         /* no further arguments, assign a default type according
  4872.            to the current subspace (CODE or DATA) */
  4873.       switch (now_seg) {
  4874.       case SEG_TEXT:        symbolP->pa_sy_dict.symbol_type = ST_CODE;break;
  4875.       case SEG_ABSOLUTE:    symbolP->pa_sy_dict.symbol_type = ST_ABSOLUTE;break;
  4876.       default:            symbolP->pa_sy_dict.symbol_type = ST_DATA;
  4877.       }
  4878. #else
  4879.       /* In ELF, if the section is undefined, then the symbol is undefined */
  4880.       /* Since this is an import, leave the section undefined.    */
  4881.       S_SET_SEGMENT(symbolP,&bfd_und_section);
  4882. #endif
  4883.     }
  4884.       
  4885.  
  4886.     demand_empty_rest_of_line();
  4887.     return;
  4888. }
  4889.  
  4890. void pa_label()
  4891. {
  4892.     register char *name;
  4893.     register char c;
  4894.     register char *p;
  4895.  
  4896.     name = input_line_pointer;
  4897.     c = get_symbol_end();
  4898.     /* just after name is now '\0' */
  4899.  
  4900.     if ( strlen(name) > 0 ) {
  4901.       colon(name);
  4902.       p = input_line_pointer;
  4903.       *p = c;
  4904.     }
  4905.     else {
  4906.       as_warn("Missing label name on .LABEL");
  4907.     }
  4908.  
  4909.     if ( !is_end_of_statement() ) {
  4910.       as_warn("extra .LABEL arguments ignored.");
  4911.       ignore_rest_of_line();
  4912.     }
  4913.     demand_empty_rest_of_line();
  4914.     return;
  4915. }
  4916.  
  4917. void pa_leave()
  4918. {
  4919.  
  4920.   as_bad(".LEAVE encountered. gas doesn't generate exit code sequences.");
  4921.   pa_exit();
  4922.   return;
  4923. }
  4924.  
  4925. void pa_origin()
  4926. {
  4927.     s_org();     /* ORG actually allows another argument (the fill value)
  4928.                     but maybe this is OK? */
  4929.     return;
  4930. }
  4931.  
  4932. void pa_proc()
  4933. {
  4934.   call_infoS *call_info;
  4935.  
  4936.   if ( within_procedure )
  4937.     as_fatal("Nested procedures");
  4938.  
  4939.   callinfo_found = FALSE;
  4940.   within_procedure = TRUE;
  4941.   exit_processing_complete = FALSE;
  4942.  
  4943.   /* create another call_info structure */
  4944.  
  4945.   call_info = (call_infoS *)xmalloc(sizeof(call_infoS));
  4946.  
  4947.   if ( !call_info )
  4948.     as_fatal("Cannot allocate unwind descriptor\n");
  4949.  
  4950.   bzero(call_info,sizeof(call_infoS));
  4951.  
  4952.   call_info->ci_next = NULL;
  4953.  
  4954.   if ( call_info_root == NULL ) {
  4955.     call_info_root = call_info;
  4956.     last_call_info = call_info;
  4957.   }
  4958.   else {
  4959.     last_call_info->ci_next = call_info;
  4960.     last_call_info = call_info;
  4961.   }
  4962.  
  4963.   /* set up defaults on call_info structure */
  4964.  
  4965.   call_info->ci_unwind.descriptor.cannot_unwind = 1; /* PJH: Tim says gcc code
  4966.                                                         is unwindable */
  4967.   call_info->ci_unwind.descriptor.region_desc = 1;
  4968.   call_info->entry_sr = ~0;
  4969.   call_info->makes_calls = 1;
  4970.   call_info->hpux_int = 0;
  4971.  
  4972.   /* If we got a .PROC pseudo-op, we know that the function is defined
  4973.      locally. Make sure it gets into the symbol table */
  4974.   {
  4975.       label_symbolS *label_symbolP = pa_get_label();
  4976.  
  4977.       if ( label_symbolP ) {
  4978.           if ( label_symbolP->lss_label ) {
  4979. #ifdef OBJ_SOM
  4980.               label_symbolP->lss_label->sy_ref |= sym_def;
  4981. #endif
  4982.               last_call_info->start_symbol = label_symbolP->lss_label;
  4983.               label_symbolP->lss_label->bsym->flags |= BSF_FUNCTION;
  4984.           }
  4985.           else
  4986.               as_bad("Missing function name for .PROC (corrupted label)");
  4987.       }
  4988.       else
  4989.           as_bad("Missing function name for .PROC");
  4990.   }
  4991.  
  4992.   demand_empty_rest_of_line();
  4993.   return;
  4994. }
  4995.  
  4996. void pa_procend()
  4997. {
  4998.  
  4999.   if ( !within_procedure )
  5000.     as_bad("misplaced .procend");
  5001.  
  5002.   if ( !callinfo_found )
  5003.     as_bad("Missing .callinfo for this procedure");
  5004.  
  5005.   if ( within_entry_exit )
  5006.     as_bad("Missing .EXIT for a .ENTRY");
  5007.  
  5008.   if ( !exit_processing_complete )
  5009.     process_exit();
  5010.  
  5011.   within_procedure = FALSE;
  5012.   demand_empty_rest_of_line();
  5013.   return;
  5014. }
  5015.  
  5016. space_dict_chainS *pa_parse_space_stmt(space_name,create_flag)
  5017.      char *space_name;
  5018.      int create_flag;
  5019. {
  5020.   register char *name;
  5021.   register char c;
  5022.   register char *p;
  5023.   register int temp;
  5024.  
  5025.   char *ptemp;
  5026.   int spnum;
  5027.   char loadable;
  5028.   char defined;
  5029.   char private;
  5030.   char sort;
  5031. #ifdef OBJ_SOM
  5032.   segT seg;
  5033. #else
  5034.   asection * seg;
  5035. #endif
  5036.   space_dict_chainS *space;
  5037.  
  5038.   /* load default values */
  5039.   spnum = 0;
  5040.   loadable = TRUE;
  5041.   defined = TRUE;
  5042.   private = FALSE;
  5043.   if ( strcasecmp(space_name,"$TEXT$") == 0 ) {
  5044. #ifdef OBJ_SOM
  5045.     seg = SEG_TEXT;
  5046. #else
  5047.     seg = text_section;
  5048. #endif
  5049.     sort = 8;
  5050.   }
  5051.   else {
  5052. #ifdef OBJ_SOM
  5053.     seg = SEG_DATA;
  5054. #else
  5055.     seg = data_section;
  5056. #endif
  5057.     sort = 16;
  5058.   }
  5059.  
  5060.   if ( !is_end_of_statement() ) {
  5061.     print_errors = FALSE;
  5062.     ptemp = input_line_pointer + 1;
  5063.     if ( (temp = pa_parse_number(&ptemp)) >= 0 ) {
  5064.       spnum = temp;
  5065.       input_line_pointer = ptemp;
  5066.     }
  5067.     else {
  5068.       while ( !is_end_of_statement() ) {
  5069.     input_line_pointer++;
  5070.     name = input_line_pointer;
  5071.     c = get_symbol_end();
  5072.     if ( (strncasecmp(name, "SPNUM", 5) == 0) ) {
  5073.       p = input_line_pointer;
  5074.       *p = c;
  5075.       input_line_pointer++;
  5076.       temp = get_absolute_expression ();
  5077.       spnum = temp;
  5078.     }
  5079.     else if ( (strncasecmp(name, "SORT",4) == 0) ) {
  5080.       p = input_line_pointer;
  5081.       *p = c;
  5082.       input_line_pointer++;
  5083.       temp = get_absolute_expression ();
  5084.       sort = temp;
  5085.     }
  5086.     else if ( (strncasecmp(name, "UNLOADABLE",10) == 0) ) {
  5087.       p = input_line_pointer;
  5088.       *p = c;
  5089.       loadable = FALSE;
  5090.     }
  5091.     else if ( (strncasecmp(name, "NOTDEFINED",10) == 0) ) {
  5092.       p = input_line_pointer;
  5093.       *p = c;
  5094.       defined = FALSE;
  5095.     }
  5096.     else if ( (strncasecmp(name, "PRIVATE",7) == 0) ) {
  5097.       p = input_line_pointer;
  5098.       *p = c;
  5099.       private = TRUE;
  5100.     }
  5101.     else {
  5102.       as_bad("Unrecognized .SPACE argument");
  5103.       p = input_line_pointer;
  5104.       *p = c;
  5105.     }
  5106.       }
  5107.     }
  5108.     print_errors = TRUE;
  5109.   }
  5110.   if ( create_flag )
  5111.     space = create_new_space(space_name,spnum,loadable,defined,private,sort,1,seg);
  5112.   else {           /* if no creation of new space, this must be the first */
  5113.                    /* occurrence of a built-in space */
  5114.     space = is_defined_space(space_name);
  5115.     SPACE_SPNUM(space) = spnum;
  5116.     SPACE_LOADABLE(space) = loadable & 1;
  5117.     SPACE_DEFINED(space) = defined & 1;
  5118.     SPACE_PRIVATE(space) = private & 1;
  5119.     SPACE_SORT(space) = sort & 0xff;
  5120.     space->sd_defined = 1;
  5121.     space->sd_seg = seg;    
  5122.   }
  5123.   return space;
  5124. }
  5125.  
  5126. void pa_align_subseg(seg,subseg)
  5127. #ifdef OBJ_SOM
  5128.      segT seg;
  5129. #else
  5130.      asection * seg;
  5131. #endif
  5132.      subsegT subseg;
  5133. {
  5134.   subspace_dict_chainS * now_subspace;
  5135.   int alignment;
  5136.   int shift;
  5137.  
  5138.   now_subspace = pa_subsegment_to_subspace(seg,subseg);
  5139.   if ( SUBSPACE_ALIGN(now_subspace) == 0 )
  5140.     alignment = now_subspace->ssd_last_align;
  5141.   else if ( now_subspace->ssd_last_align > SUBSPACE_ALIGN(now_subspace) )
  5142.     alignment = now_subspace->ssd_last_align;
  5143.   else
  5144.     alignment = SUBSPACE_ALIGN(now_subspace);
  5145.  
  5146.   shift = 0;
  5147.   while ( (1 << shift) < alignment )
  5148.     shift++;
  5149.  
  5150.   frag_align(shift,0);
  5151. }
  5152.  
  5153. void pa_space()
  5154. {
  5155.     register char *name;
  5156.     register char c;
  5157.     register char *p;
  5158.     register int temp;
  5159.     register symbolS *    symbolP;
  5160.     register space_dict_chainS *sd_chain;
  5161.     char space_name[40];
  5162.  
  5163.     if ( within_procedure ) {
  5164.       as_bad("Can\'t change spaces within a procedure definition. Ignored");
  5165.       ignore_rest_of_line();
  5166.     }
  5167.     else {
  5168.       if (strncasecmp(input_line_pointer, "$text$", 6) == 0) {
  5169.     input_line_pointer += 6;
  5170.     sd_chain = is_defined_space("$TEXT$");
  5171.     if ( sd_chain == NULL )
  5172.       sd_chain = pa_parse_space_stmt("$TEXT$",1);
  5173.         else if ( sd_chain->sd_defined == 0 )
  5174.       sd_chain = pa_parse_space_stmt("$TEXT$",0);
  5175.  
  5176.     current_space = sd_chain;
  5177.     SPACE_DEFINED(current_space) = 1;
  5178.     current_space->sd_defined = 1;
  5179. #ifdef OBJ_SOM
  5180.     if ( now_seg != SEG_TEXT )   /* no need to align if we are already there */
  5181. #else
  5182.     if ( now_seg != text_section )/* no need to align if we are already there */
  5183. #endif
  5184.       pa_align_subseg(now_seg,now_subseg);
  5185.  
  5186. #ifdef OBJ_SOM
  5187.     subseg_new (SEG_TEXT, sd_chain->sd_last_subseg);
  5188.     current_subspace = pa_subsegment_to_subspace(SEG_TEXT,
  5189.                              sd_chain->sd_last_subseg);
  5190. #else
  5191.     subseg_new ((char *)text_section->name, sd_chain->sd_last_subseg);
  5192.     current_subspace = pa_subsegment_to_subspace(text_section,
  5193.                              sd_chain->sd_last_subseg);
  5194. #endif
  5195.     demand_empty_rest_of_line();
  5196.     return;
  5197.       }
  5198.       if (strncasecmp(input_line_pointer, "$private$", 9) == 0) {
  5199.     input_line_pointer += 9;
  5200.     sd_chain = is_defined_space("$PRIVATE$");
  5201.     if ( sd_chain == NULL )
  5202.       sd_chain = pa_parse_space_stmt("$PRIVATE$",1);
  5203.         else if ( sd_chain->sd_defined == 0 )
  5204.       sd_chain = pa_parse_space_stmt("$PRIVATE$",0);
  5205.  
  5206.     current_space = sd_chain;
  5207.     SPACE_DEFINED(current_space) = 1;
  5208.     current_space->sd_defined = 1;
  5209. #ifdef OBJ_SOM
  5210.     if ( now_seg != SEG_DATA )   /* no need to align if we are already there */
  5211. #else
  5212.     if ( now_seg != data_section )/* no need to align if we are already there */
  5213. #endif
  5214.       pa_align_subseg(now_seg,now_subseg);
  5215. #ifdef OBJ_SOM
  5216.     subseg_new (SEG_DATA, sd_chain->sd_last_subseg);
  5217.     current_subspace = pa_subsegment_to_subspace(SEG_DATA,
  5218.                              sd_chain->sd_last_subseg);
  5219. #else
  5220.     subseg_new ((char *)data_section->name, sd_chain->sd_last_subseg);
  5221.     current_subspace = pa_subsegment_to_subspace(data_section,
  5222.                              sd_chain->sd_last_subseg);
  5223. #endif
  5224.     demand_empty_rest_of_line();
  5225.     return;
  5226.       }
  5227.       if (strncasecmp(input_line_pointer,
  5228.               GDB_DEBUG_SPACE_NAME,strlen(GDB_DEBUG_SPACE_NAME)) == 0) {
  5229.     input_line_pointer += strlen(GDB_DEBUG_SPACE_NAME);
  5230.         sd_chain = is_defined_space(GDB_DEBUG_SPACE_NAME);
  5231.     if ( sd_chain == NULL )
  5232.       sd_chain = pa_parse_space_stmt(GDB_DEBUG_SPACE_NAME,1);
  5233.         else if ( sd_chain->sd_defined == 0 )
  5234.       sd_chain = pa_parse_space_stmt(GDB_DEBUG_SPACE_NAME,0);
  5235.  
  5236.     current_space = sd_chain;
  5237.     SPACE_DEFINED(current_space) = 1;
  5238.     current_space->sd_defined = 1;
  5239. #ifdef OBJ_SOM
  5240.     if ( now_seg != SEG_GDB )   /* no need to align if we are already there */
  5241.       pa_align_subseg(now_seg,now_subseg);
  5242.     subseg_new (SEG_GDB, sd_chain->sd_last_subseg);
  5243.     current_subspace = pa_subsegment_to_subspace(SEG_GDB,
  5244.                              sd_chain->sd_last_subseg);
  5245. #else
  5246.     if ( now_seg != gdb_section ) /* no need to align if we are already there */
  5247.       pa_align_subseg(now_seg,now_subseg);
  5248.     subseg_new ((char *)gdb_section->name, sd_chain->sd_last_subseg);
  5249.     current_subspace = pa_subsegment_to_subspace(gdb_section,
  5250.                              sd_chain->sd_last_subseg);
  5251. #endif
  5252.     demand_empty_rest_of_line();
  5253.     return;
  5254.       }
  5255.  
  5256.       /* it could be a space specified by number */
  5257.  
  5258.       if ( (temp = pa_parse_number(&input_line_pointer)) >= 0 ) {
  5259.     if ( sd_chain = pa_find_space_by_number(temp) ) {
  5260.       current_space = sd_chain;
  5261.       SPACE_DEFINED(current_space) = 1;
  5262.       current_space->sd_defined = 1;
  5263.       if ( now_seg != sd_chain->sd_seg ) /* don't align if we're already there */
  5264.         pa_align_subseg(now_seg,now_subseg);
  5265. #ifdef OBJ_SOM
  5266.       subseg_new (sd_chain->sd_seg, sd_chain->sd_last_subseg);
  5267. #else
  5268.       subseg_new ((char *)sd_chain->sd_seg->name, sd_chain->sd_last_subseg);
  5269. #endif
  5270.       current_subspace = pa_subsegment_to_subspace(sd_chain->sd_seg,
  5271.                                sd_chain->sd_last_subseg);
  5272.       demand_empty_rest_of_line();
  5273.       return;
  5274.     }
  5275.       }
  5276.  
  5277.       /* not a number, attempt to create a new space */
  5278.  
  5279.       name = input_line_pointer;
  5280.       c = get_symbol_end();
  5281.       space_name[0] = 0x00;
  5282.       strcpy(space_name,name);
  5283.       *input_line_pointer = c;
  5284.  
  5285.       sd_chain = pa_parse_space_stmt(space_name,1);
  5286.       current_space = sd_chain;
  5287.       SPACE_DEFINED(current_space) = 1;
  5288.       current_space->sd_defined = 1;
  5289.       if ( now_seg != sd_chain->sd_seg ) /* don't align if we're already there */
  5290.     pa_align_subseg(now_seg,now_subseg);
  5291. #ifdef OBJ_SOM
  5292.       subseg_new (sd_chain->sd_seg, sd_chain->sd_last_subseg);
  5293. #else
  5294.       subseg_new ((char *)sd_chain->sd_seg->name, sd_chain->sd_last_subseg);
  5295. #endif
  5296.       current_subspace = pa_subsegment_to_subspace(sd_chain->sd_seg,
  5297.                            sd_chain->sd_last_subseg);
  5298.       demand_empty_rest_of_line();
  5299.     }
  5300.     return;
  5301. }
  5302.  
  5303. void pa_spnum()
  5304. {
  5305.     register char *name;
  5306.     register char c;
  5307.     register char *p;
  5308.     space_dict_chainS *space;
  5309.  
  5310.     name = input_line_pointer;
  5311.     c = get_symbol_end();
  5312.     space = is_defined_space(name);
  5313.     if ( space ) {
  5314.       p = frag_more (4);
  5315.       /* put bytes in right order. */
  5316.       md_number_to_chars (p,SPACE_SPNUM(space),4);
  5317.     }
  5318.     else
  5319.       as_warn("Undefined space: '%s' Assuming space number = 0.",name);
  5320.  
  5321.     *input_line_pointer = c;
  5322.     demand_empty_rest_of_line();
  5323.     return;
  5324. }
  5325.  
  5326. static
  5327. int is_power_of_2(value)
  5328.      int value;
  5329. {
  5330.   int shift;
  5331.  
  5332.   shift = 0;
  5333.   while ( ( 1 << shift ) != value && shift < 32 )
  5334.     shift++;
  5335.  
  5336.   if ( shift >= 32 )
  5337.     shift = 0;
  5338.   return shift;
  5339. }
  5340.  
  5341. void pa_subspace()
  5342. {
  5343.     register char *name;
  5344.     register char c;
  5345.     register char *p;
  5346.     register int temp;
  5347.     register symbolS *    symbolP;
  5348.     
  5349.     char loadable,code_only,common,dup_common,zero;
  5350.     char sort;
  5351.     int number;
  5352.     int i;
  5353.     int access;
  5354.     int space_index;
  5355.     int alignment;
  5356.     int quadrant;
  5357.     int subseg;
  5358.     space_dict_chainS *space;
  5359.     subspace_dict_chainS *ssd;
  5360.     subspace_dict_chainS *ssdCh;
  5361.     char *ss_name;
  5362.     int is_power_of_2();
  5363.  
  5364.     if ( within_procedure ) {
  5365.       as_bad("Can\'t change subspaces within a procedure definition. Ignored");
  5366.       ignore_rest_of_line();
  5367.     }
  5368.     else {
  5369.       name = input_line_pointer;
  5370.       c = get_symbol_end();
  5371.       space = pa_segment_to_space(now_seg);
  5372.       ssd = is_defined_subspace(name,space->sd_last_subseg);
  5373.  
  5374.       ss_name = xmalloc(strlen(name)+1);
  5375.       strcpy(ss_name,name);
  5376.  
  5377.       *input_line_pointer = c;
  5378.  
  5379.       /* load default values */
  5380.       sort = 0;
  5381.       access = 0x7f;
  5382.       loadable = 1;
  5383.       common = 0;
  5384.       dup_common = 0;
  5385.       code_only = 0;
  5386.       zero = 0;
  5387.       space_index = ~0;       /* filled in when the .o file is written */
  5388.       alignment = 0;    /* alignment=0 means no ALIGN= appeared on the .SUBSPA */
  5389.                         /* pseudo-op. The default will be the largest .ALIGN */
  5390.                         /* encountered (or 1 if no .ALIGN is encountered) */
  5391.       quadrant = 0;
  5392.  
  5393.       if ( ssd ) {
  5394.     if ( ssd->ssd_defined ) {
  5395. #ifdef OBJ_SOM
  5396.       subseg_new(now_seg,ssd->ssd_subseg);
  5397. #else
  5398.       /* subseg_new(now_seg->name,ssd->ssd_subseg); */
  5399.       subseg_new((char *)ssd->ssd_seg->name,ssd->ssd_subseg);
  5400. #endif
  5401.       if ( !is_end_of_statement() ) {
  5402.         as_warn("Parameters of an existing subspace can\'t be modified");
  5403.       }
  5404.       demand_empty_rest_of_line();
  5405.       return;
  5406.     }
  5407.     else {
  5408.       ssd->ssd_defined = 1;
  5409.     }
  5410.       }
  5411.       else {
  5412.     /* a new subspace */
  5413.     /* load default values */
  5414.     i = 0;
  5415.     while ( pa_def_subspaces[i].name ) {
  5416.       if ( strcasecmp(pa_def_subspaces[i].name,ss_name) == 0 ) {
  5417.         loadable = pa_def_subspaces[i].loadable;
  5418.         common = pa_def_subspaces[i].common;
  5419.         dup_common = pa_def_subspaces[i].dup_common;
  5420.         code_only = pa_def_subspaces[i].code_only;
  5421.         zero = pa_def_subspaces[i].zero;
  5422.         space_index = pa_def_subspaces[i].space_index;
  5423.         /* alignment = pa_def_subspaces[i].alignment; */
  5424.         alignment = 0;
  5425.         quadrant = pa_def_subspaces[i].quadrant;
  5426.         access = pa_def_subspaces[i].access;
  5427.         sort = pa_def_subspaces[i].sort;
  5428.         break;
  5429.       }
  5430.       i++;
  5431.     }
  5432.       }
  5433.  
  5434.       if ( !is_end_of_statement() ) {
  5435.     input_line_pointer++;
  5436.     while ( !is_end_of_statement() ) {
  5437.       name = input_line_pointer;
  5438.       c = get_symbol_end();
  5439.       if ( (strncasecmp(name, "QUAD", 4) == 0) ) {
  5440.         *input_line_pointer = c;
  5441.         input_line_pointer++;
  5442.         temp = get_absolute_expression ();
  5443.         quadrant = temp;
  5444.       }
  5445.       else if ( (strncasecmp(name, "ALIGN", 5) == 0) ) {
  5446.         *input_line_pointer = c;
  5447.         input_line_pointer++;
  5448.         temp = get_absolute_expression ();
  5449.         alignment = temp;
  5450.         if ( !is_power_of_2(alignment) ) {
  5451.           as_bad("Alignment must be a power of 2");
  5452.           alignment = 1;
  5453.         }
  5454.       }
  5455.       else if ( (strncasecmp(name, "ACCESS",6) == 0) ) {
  5456.         *input_line_pointer = c;
  5457.         input_line_pointer++;
  5458.         temp = get_absolute_expression ();
  5459.         access = temp;
  5460.       }
  5461.       else if ( (strncasecmp(name, "SORT",4) == 0) ) {
  5462.         *input_line_pointer = c;
  5463.         input_line_pointer++;
  5464.         temp = get_absolute_expression ();
  5465.         sort = temp;
  5466.       }
  5467.       else if ( (strncasecmp(name, "CODE_ONLY",9) == 0) ) {
  5468.         *input_line_pointer = c;
  5469.         code_only = 1;
  5470.       }
  5471.       else if ( (strncasecmp(name, "UNLOADABLE",10) == 0) ) {
  5472.         *input_line_pointer = c;
  5473.         loadable = 0;
  5474.       }
  5475.       else if ( (strncasecmp(name, "COMMON",6) == 0) ) {
  5476.         *input_line_pointer = c;
  5477.         common = 1;
  5478.       }
  5479.       else if ( (strncasecmp(name, "DUP_COMM",8) == 0) ) {
  5480.         *input_line_pointer = c;
  5481.         dup_common = 1;
  5482.       }
  5483.       else if ( (strncasecmp(name, "ZERO",4) == 0) ) {
  5484.         *input_line_pointer = c;
  5485.         zero = 1;
  5486.       }
  5487.       else {
  5488.         as_bad("Unrecognized .SUBSPACE argument");
  5489.       }
  5490.       if ( !is_end_of_statement() )
  5491.         input_line_pointer++;
  5492.     }
  5493.       }
  5494.       space = pa_segment_to_space(now_seg);
  5495.       if ( ssd ) {
  5496.     current_subspace = update_subspace(ss_name,1,loadable,code_only,
  5497.                        common,dup_common,sort,zero,access,
  5498.                        space_index,alignment,quadrant,
  5499.                        ssd->ssd_subseg);
  5500.       }
  5501.       else {
  5502.     current_subspace = create_new_subspace(space,ss_name,1,loadable,code_only,
  5503.                            common,dup_common,zero,sort,
  5504.                            access,space_index,alignment,
  5505.                            quadrant,now_seg);
  5506.       }
  5507.       SUBSPACE_SUBSPACE_START(current_subspace) = pa_subspace_start(space,quadrant);
  5508.  
  5509.       demand_empty_rest_of_line();
  5510. #ifdef OBJ_SOM
  5511.       subseg_new (current_subspace->ssd_seg, current_subspace->ssd_subseg);
  5512. #else
  5513.       subseg_new ((char *)current_subspace->ssd_seg->name, current_subspace->ssd_subseg);
  5514. #endif
  5515.     }
  5516.     return;
  5517. }
  5518.  
  5519. /* For ELF, this function serves one purpose:  to setup the st_size    */
  5520. /* field of STT_FUNC symbols.  To do this, we need to scan the         */
  5521. /* call_info structure list, determining st_size in one of two possible    */
  5522. /* ways:                                */
  5523.  
  5524. /*    1. call_info->start_frag->fr_fix has the size of the fragment.    */
  5525. /*       This approach assumes that the function was built into a     */
  5526. /*       single fragment.  This works for most cases, but might fail.    */
  5527. /*       For example, if there was a segment change in the middle of    */
  5528. /*       the function.                        */
  5529.  
  5530. /*    2. The st_size field is the difference in the addresses of the    */
  5531. /*       call_info->start_frag->fr_address field and the fr_address    */
  5532. /*       field of the next fragment with fr_type == rs_fill and    */
  5533. /*       fr_fix != 0.                            */
  5534.  
  5535. void tc_final_processing_hook()
  5536. {
  5537.     extern call_infoS *call_info_root;
  5538.  
  5539.     call_infoS *ciP;
  5540.  
  5541.     for ( ciP = call_info_root; ciP; ciP = ciP->ci_next ) {
  5542.         elf_symbol_type *esym = (elf_symbol_type *)ciP->start_symbol->bsym;
  5543.         esym->internal_elf_sym.st_size =
  5544.             ciP->end_symbol->bsym->value
  5545.                 - ciP->start_symbol->bsym->value + 4;
  5546.     }
  5547. }
  5548.